重命名子目录和文件

时间:2013-04-12 23:35:49

标签: bash unix directory

我有一个使用for循环的脚本,它会重命名文件夹和文件。该脚本将获取文件和文件夹列表并有条件地重命名它们。我将使用以下命令调用该文件:

find test/* -exec ./replace.sh {} \;

我的replace.sh脚本将包含类似于:

的内容
for i in $@
mv $OLDFILE $NEWFILE
done
之前已经设置了
    $ OLDFILE和$ NEWFILE,我不相信会有任何问题。

    当我遇到子目录时,我的问题出现了。最初,我会有像这样的文件夹:

    folder_1
    
     -file1
    
     -file2
    

    当我的脚本将folder_1更改为folderX1时,下一个参数folder_1 / file1将无效,因为更改的路径将是folderX1 / file1。我想我可以创建一个堆栈,其中包含正在更改的文件夹列表,稍后将其弹出以重命名文件,但这在bash上看起来很难。有没有更好的方法让我失踪?

    P.S我可以多次运行该程序来浏览所有子目录,但这看起来效率不高。

2 个答案:

答案 0 :(得分:2)

您可以将-depth添加到find命令。这将在目录本身之前处理目录的文件。有关详细信息,请参阅man find

答案 1 :(得分:1)

您的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更改了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
$