递归重命名文件夹

时间:2017-03-06 23:04:18

标签: recursion sed rename

我有一个Windows备份程序,它在最后创建了一个带有“$”的大量子目录。同一备份程序的Linux客户端期望目录名末尾有“:”以恢复文件夹。某些文件夹具有“$”而其他文件夹没有 - 与内部版本控制系统有关。

如果我将文件从Windows客户端恢复到另一个Windows框,则备份程序运行良好。该程序在Windows中使用“$”,因为“:”在路径中无效。

我正在寻找bash中的递归重命名,它将遍历一个路径,并在末尾找到一个带有“$”字符的所有文件夹,并将其替换为“:

我的测试数据是:

./a$
./b$
./c$
./white space$
./white space$/another test$
./white space$/another test$/a$
./white space$/another test$/b$
./white space$/another test$/x
./white space$/another test$/y
./white space$/test
./white space$/test 2
./white space$/testing$

我试过了:

find . -type d -name "*$" 

它为我提供了需要重命名的文件夹列表

./a$
./b$
./c$
./white space$
./white space$/another test$
./white space$/another test$/a$
./white space$/another test$/b$
./white space$/testing$


find . -type d -name "*$" | sed 's/$$/\:/'   

给了我正在寻找的最终结果

./a:
./b:
./c:
./white space:
./white space$/another test:
./white space$/another test$/a:
./white space$/another test$/b:
./white space$/testing:

但是我不能让它在同一步骤中重命名。此外,我需要它以相反的顺序工作(从最深的匹配开始并返回工作),以便第一次重命名不会使其余的失败。

1 个答案:

答案 0 :(得分:0)

您可以使用this solution来处理所有空格和特殊字符,然后使用printf '%d'可以获取每个匹配目录的深度,然后执行降序sort并构建一个通过rename执行的awk命令将sh执行:

while IFS= read -r -d '' n; do
  printf '%q\n' "$n"
done < <(find . -type d -name "*$" -printf '%d|' -print0) | \
sort -r -k1 | \
awk -F '|' '{ printf "rename -v -n '\''s/\\$$/:/'\'' %s \n",$2 }' | \
sh

rename -n只会打印要重命名的文件名,如果您准备好了,请执行重命名操作,删除-n

while IFS= read -r -d '' n; do
  printf '%q\n' "$n"
done < <(find . -type d -name "*$" -printf '%d|' -print0) | \
sort -r -k1 | \
awk -F '|' '{ printf "rename -v '\''s/\\$$/:/'\'' %s \n",$2 }' | \
sh

显示进度

data=$(while IFS= read -r -d '' n; do
  printf '%q\n' "$n"
done < <(find . -type d -name "*$" -printf '%d|' -print0) | \
sort -r -k1);

count=$(echo "$data" | awk 'END{ print NR}');

echo "$data" | awk -F '|' -v count=$count '{ printf "echo -n \""NR"/"count" file : \";rename -v -n  '\''s/\\$$/:/'\'' %s \n",$2 }' | \
sh

输出:

1/8 file : ./white space$/another test$/b$ renamed as ./white space$/another test$/b:
2/8 file : ./white space$/another test$/a$ renamed as ./white space$/another test$/a:
3/8 file : ./white space$/testing$ renamed as ./white space$/testing:
4/8 file : ./white space$/another test$ renamed as ./white space$/another test:
5/8 file : ./white space$ renamed as ./white space:
6/8 file : ./c$ renamed as ./c:
7/8 file : ./b$ renamed as ./b:
8/8 file : ./a$ renamed as ./a:

替代

更直接的解决方案,使用rnm批量重命名工具:

rnm -rs '/\$$/:/g' -dp -1 *