你的find
使用有问题。第一个选项是搜索的开始位置,因此您不想在那里使用 glob。如果您只想要其中的文件test/
而不想要其任何子目录,请-depth
按照 Olaf 的建议使用该选项。
您实际上不需要使用单独的脚本来处理此重命名。find
如果你不介意有点乱,它可以在命令行中完成。
要仅处理顶级文件,您可以这样做:
$ touch foo.txt bar.txt baz.ext
$ find test -depth 1 -type f -name \*.txt -exec bash -c 'f="{}"; mv -v "{}" "${f/.txt/.csv}"' \;
./foo.txt -> ./foo.csv
./bar.txt -> ./bar.csv
$
但是您的担忧是有效的——find
将建立一个匹配列表,如果您-exec
从 under 更改列表find
,一些重命名将失败。
我怀疑您最快的解决方案是分两个阶段(不是几个阶段)执行此操作:一个用于文件,然后一个用于目录。(或者更改顺序,我认为这无关紧要。)
$ mkdir foo_1; touch red_2 foo_1/blue_3
$ find . -type f -name \*_\* -exec bash -c 'f="{}"; mv -v "{}" "${f%_?}X${f##*_}"' \;
./foo_1/blue_3 -> ./foo_1/blueX3
./red_2 -> ./redX2
$ find . -type d -name \*_\* -exec bash -c 'f="{}"; mv -v "{}" "${f%_?}X${f##*_}"' \;
./foo_1 -> ./fooX1
Bash 参数扩展将使您走得更远。
另一个选项,取决于您的实现find
,是-d
选项:
-d Cause find to perform a depth-first traversal, i.e., directories
are visited in post-order and all entries in a directory will be
acted on before the directory itself. By default, find visits
directories in pre-order, i.e., before their contents. Note, the
default is not a breadth-first traversal.
所以:
$ mkdir -p foo_1/bar_2; touch red_3 foo_1/blue_4 foo_1/bar_2/green_5
$ find . -d -name \*_\* -exec bash -c 'f="{}"; mv -v "{}" "${f%_?}X${f##*_}"' \;
./foo_1/bar_2/green_5 -> ./foo_1/bar_2/greenX5
./foo_1/bar_2 -> ./foo_1/barX2
./foo_1/blue_4 -> ./foo_1/blueX4
./foo_1 -> ./fooX1
./red_3 -> ./redX3
$