我有这个文件列表:
$ find .
.
./ sdf.sdf
./ dkfjd L
./aaa*
./aaa*bbb
./aaa:bbb
./b
./b/c
./b/c/xxx.123
如果我这样做,rename -n -e 's/\*|\:/_/g' -e 's/^\ +//' *
我会得到我想要的:
' sdf.sdf' would be renamed to 'sdf.sdf'
' dkfjd L' would be renamed to 'dkfjd L'
'aaa*' would be renamed to 'aaa_'
'aaa*bbb' would be renamed to 'aaa_bbb'
'aaa:bbb' would be renamed to 'aaa_bbb'
但如果我这样做find . | rename -n -e 's/\*|\:/_/g' -e 's/^\ +//'
我会得到:
Reading filenames from STDIN
'./aaa*' would be renamed to './aaa_'
'./aaa*bbb' would be renamed to './aaa_bbb'
'./aaa:bbb' would be renamed to './aaa_bbb'
为什么第二个命令看不到以空格开头的目录?
我也尝试过,find . -print0 | rename -n -0 -e 's/\*|\:/_/g' -e 's/^\ +//'
但这没有什么区别。
我需要rename
在一棵大树上运行;还有其他方法可以递归到子目录吗?
注意:最终我将使用mdfind
not来使用它find
,所以我不能使用该-exec
选项。
答案1
这将重命名文件和目录(嗯,任何匹配的东西,真的)。我已经指定-depth
,在安全处理内容之前不会重命名更高级别的目录。
find . -depth | rename -n -e 'y{*:}{_}; s{(?<=/)\s+(?!.*/.*$)}{}'
重命名是由两个 RE 构建的。 (我的rename
仅接受一个-e {RE}
参数,因此我将这两个操作连接到一个参数中。)
第一个很简单:用ory{*:}{_}
代替(又名 Unix )。*
:
_
tr
第二种更复杂并且使用向后看和向前看以匹配必要的组件。它表示要处理的表达式\s+
应紧接在 之前/
,并且后面不能跟在/
文件名其余部分的任何位置。
输出
rename(./ dkfjd L, ./dkfjd L)
rename(./aaa*, ./aaa_)
rename(./aaa*bbb, ./aaa_bbb)
rename(./ sdf.sdf, ./sdf.sdf)
rename(./aaa:bbb, ./aaa_bbb)