调整文件重命名脚本,以便搜索子目录中的每个文件

时间:2016-07-26 12:05:29

标签: arrays linux bash rename

我有一个.csv文件,其中看起来像这样:

unnamed_0711-42_p1.mov,day1_0711-42_p1.mov
unnamed_0711-51_p2.mov,day1_0711-51_p2.mov
unnamed_0716-42_p1_2.mov,day1_0716-42_p1_2.mov
unnamed_0716-51_p2_2.mov,day1_0716-51_p2_2.mov

我已编写此代码,将字段1中的名称(例如unnamed_0711-42_p1.mov)重命名为字段2中的名称(例如day1_0711-42_p1.mov)。

csv=/location/rename.csv

cat $csv | while IFS=, read -r -a arr; do mv "${arr[@]}"; done

但是,此脚本仅在它和所有需要重命名的文件位于同一目录中时才有效。以前这没关系,但现在我需要在各个子目录中查找文件(不添加我的.csv文件的完整路径)。

如何调整我的脚本以便搜索子目录中的文件,然后像以前一样更改名称?

2 个答案:

答案 0 :(得分:1)

脚本

while IFS=, read -ra arr # -r to prevent mangling backslashes
do
 find . -type f -name "${arr[0]}" -printf "mv '%p' '%h/${arr[1]}'" | bash
done<csvfile

应该这样做。

请参阅[ find ]联机帮助页以了解printf说明符如%p,%h

答案 1 :(得分:1)

使这项工作的一种简单方法,虽然它会导致效率低下,但是:

for D in `find . -type d`
do
    cat $csv | while IFS=, read -r -a arr; do mv "${arr[@]}"; done
done

这将为当前目录中的每个目录运行您的命令,但这会运行每个子目录的整个文件名列表。另一种方法是在处理它的名称时搜索每个文件:

csv=files.csv
while IFS=, read -ra arr; do
    while IFS= read -r -d '' old_file; do
        old_dir=$(dirname "$old_file")
        mv "$old_file" "$old_dir/${arr[1]}"
    done < <(find . -name "${arr[0]}" -print0)
done<"$csv"

这使用find找到每个旧文件名,然后使用dirname获取旧文件的目录(我们需要这样,以便mv不会将重命名的文件放入不同的目录)。

这将重命名每个文件的每个实例(即,如果unnamed_0711-42_p1.mov出现在多个子目录中,则每个实例将重命名为day1_0711-42_p1.mov)。如果你知道每个文件名只会出现一次,你可以通过在管道之前的find命令末尾添加-print -quit来加快速度。