如何在Linux中使用shell重命名数千个目录,并删除以“it”开头的最后9个字符?

x33g5p2x  于 2023-05-22  发布在  Linux
关注(0)|答案(4)|浏览(119)

我需要更改上千个目录和子目录的名称,将名称的最后9个字符删除。这最后9个字符以“it”开头。
示例:193- 105 kg-dal-brasile-it 8 petfo 7至193- 105 kg-dal-brasile
我尝试了以下命令:

find /Users/myuser/Downloads/damod -type d -iname '*' mv "$i" "${i:50: -2}"

我用的是OSX,我安装了Brew。我非常感谢任何帮助。
我已经看到了建议的情况下,insted在文章中保持最后一个carachter与此公式(.{48}$),我的情况是不是一个重复的感谢

carvr3hs

carvr3hs1#

findsedxargs一起使用:

find "$test_dir" ! -path "$test_dir" -type d -print0 | sed -z 'p;s/.\{10\}$//' | xargs -0 -n 2 mv

对于成千上万的文件,您可以使用xargs -P开关来启用并行处理。使用多达4个并行进程的示例:

find "$test_dir" ! -path "$test_dir" -type d -print0 | sed -z 'p;s/.\{10\}$//' | xargs -0 -n 2 -P 4 mv

--或--
使用find和bash进程替换来循环目录并重命名它们:

while IFS= read -r -d '' d ; do 
    mv "$d" "${d::${#d}-10}"
done < <(find "$test_dir" ! -path "$test_dir" -type d -print0)

注意:OP表示希望删除尾随的9个字符,但OP的示例显示删除了10个字符(包括原始示例目录名称中的最后一个'-')。
示例脚本:

#!/bin/bash

test_dir=""

setup() {
    test_dir=$(mktemp -d -p .) 
    for i in {1..9} ; do mkdir "${test_dir}/19$i-105kg-dal-brasile-it8petfo$i" ; done
}

cleanup() {      
  rm -rf "$test_dir"
}

list_dirs() {
    while IFS= read -r -d '' d ; do 
        printf "%s\n" "$d"
    done < <(find "$test_dir" ! -path "$test_dir" -type d -print0) | sort
}

trap cleanup EXIT

setup
list_dirs

# while IFS= read -r -d '' d ; do 
#     mv "$d" "${d::${#d}-10}"
# done < <(find "$test_dir" ! -path "$test_dir" -type d -print0)

find "$test_dir" ! -path "$test_dir" -type d -print0 | sed -z 'p;s/.\{10\}$//' | xargs -0 -n 2 -P 4 mv

list_dirs

输出:

./tmp.V0s210g0PM/191-105kg-dal-brasile-it8petfo1
./tmp.V0s210g0PM/192-105kg-dal-brasile-it8petfo2
./tmp.V0s210g0PM/193-105kg-dal-brasile-it8petfo3
./tmp.V0s210g0PM/194-105kg-dal-brasile-it8petfo4
./tmp.V0s210g0PM/195-105kg-dal-brasile-it8petfo5
./tmp.V0s210g0PM/196-105kg-dal-brasile-it8petfo6
./tmp.V0s210g0PM/197-105kg-dal-brasile-it8petfo7
./tmp.V0s210g0PM/198-105kg-dal-brasile-it8petfo8
./tmp.V0s210g0PM/199-105kg-dal-brasile-it8petfo9
./tmp.V0s210g0PM/191-105kg-dal-brasile
./tmp.V0s210g0PM/192-105kg-dal-brasile
./tmp.V0s210g0PM/193-105kg-dal-brasile
./tmp.V0s210g0PM/194-105kg-dal-brasile
./tmp.V0s210g0PM/195-105kg-dal-brasile
./tmp.V0s210g0PM/196-105kg-dal-brasile
./tmp.V0s210g0PM/197-105kg-dal-brasile
./tmp.V0s210g0PM/198-105kg-dal-brasile
./tmp.V0s210g0PM/199-105kg-dal-brasile
r6hnlfcb

r6hnlfcb2#

Bash有变量替换,你可以用途:

for f in $(find ~/Downloads/damod -type d); do echo mv "$f" "${f/%-it*/}"; done

上面的命令实际上并不重命名。它只是显示了动作。如果输出看起来不错,那么您可以删除“echo”部分,并将其重新命名为真实的。
${f/%-it*/}表达式表示 * 搜索suffix(由%符号表示)“-it*”并将其替换为nothing(第二个正斜杠后面没有文本)。

juzqafwq

juzqafwq3#

一个建议是使用locate:
1 -查找目录:

locate "/directory"

2 -使用grep搜索以“it”结尾的行:

grep -E "/it[^/]{9}$"

3 -读取每个目录:

while read -r dir;

4 -通过删除最后9个字符获得目录的新名称:

n_name=$(echo "$dir" | sed -E 's/(.*)(it[^/]{9})$/\1/')

5 -重命名目录:

mv "$dir" "$n_name"

例如:

locate "/directory" | grep -E "/it[^/]{9}$" | while read -r dir; do n_name=$(echo "$dir" | sed -E 's/(.*)(it[^/]{9})$/\1/'); mv "$dir" "$n_name"; done

脚本代码:

#!/bin/bash

directory_path="/directory"

locate "$directory_path" | grep -E "/it[^/]{9}$" | while read -r dir; do
    n_name=$(echo "$dir" | sed -E 's/(.*)(it[^/]{9})$/\1/')
    mv "$dir" "$n_name"
done
ie3xauqp

ie3xauqp4#

Homebrew提供Perl rename

top="/Users/myuser/Downloads/damod"

# check what would happen:
find "$top" -type d -print0 | rename -n -0 -d 's/-it.{7}$//'

# actually run the command:
find "$top" -type d -print0 | rename -v -0 -d 's/-it.{7}$//'

rename将在新名称的内容已经存在时发出抱怨。

相关问题