[英]How can i find and rename multiple files
I have multiple files in multiple directories and i have to rename these files from lowercase to uppercase;我在多个目录中有多个文件,我必须将这些文件从小写重命名为大写; the file extension may vary and needs to be in lowercase (should be renamed too for files with extensions in uppercase).文件扩展名可能会有所不同,并且需要小写(对于具有大写扩展名的文件也应该重命名)。
NB: I have rename
version from util-linux
on CentOS Linux7.注意:我在 CentOS Linux7 上rename
了util-linux
版本。
i tried this :我试过这个:
find /mydir -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/$1\/\U$2/' {} \;
find /mydir -depth | xargs -n 1 rename -v 's/(.*)\/([^\/]*)/$2\/\L$2/' {} \;
but it's not working it changes nothing and i have no output.但它不工作它没有任何改变,我没有输出。
Itried another solution :尝试了另一种解决方案:
for SRC in `find my_root_dir -depth`
do
DST=`dirname "${SRC}"`/`basename "${SRC}" | tr '[A-Z]' '[a-z]'`
if [ "${SRC}" != "${DST}" ]
then
[ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed"
fi
done
this one partially works but transforms the files extensions to uppercase too.这个部分有效,但也将文件扩展名转换为大写。
Any suggestions on how to keep/transform the extensions to lowercase ?关于如何将扩展保留/转换为小写的任何建议?
Thank you!谢谢!
rename
-independent solution (using find
together with mv
) rename
独立解决方案(将find
与mv
一起使用)You can rename all files in a directory with a following command:您可以使用以下命令重命名目录中的所有文件:
for i in $( ls | grep [A-Z] ); do mv -i $i `echo $i | tr 'A-Z' 'a-z'`; done
First part ( for i in $( ls | grep [AZ] );
) looks for all uppercase characters and executes until all files are "scanned".第一部分( for i in $( ls | grep [AZ] );
)查找所有大写字符并执行,直到所有文件都被“扫描”。
Second part (``) turns all uppercase characters into lowercase ones.第二部分 (``) 将所有大写字符转换为小写字符。
rename
dependent solution基于 Perl 的rename
依赖解决方案rename -f 'y/A-Z/a-z/' *
This command changes uppercase characters to the lowercase ones.此命令将大写字符更改为小写字符。 -f
option allows overwriting of existing files, but it is not necessary. -f
选项允许覆盖现有文件,但这不是必需的。
Possible solution with Perl rename
: Perl rename
的可能解决方案:
find /mydir -depth -type f -exec rename -v 's/(.*\/)?([^.]*)/$1\U$2/' {} +
The commands in the question have several problems.问题中的命令有几个问题。
You seem to confuse the syntax of find
's -exec
action and xargs
.您似乎混淆了find
的-exec
操作和xargs
的语法。
find /mydir -depth -type f -exec rename -v 'substitution_command' {} \;
find /mydir -depth -type f| xargs -n 1 rename -v 'substitution_command'
The xargs
version has problems in case a file name contains a space.如果文件名包含空格, xargs
版本会出现问题。
If you replace \;
如果你替换\;
with +
, multiple file names are passed to one invocation of rename
.使用+
,将多个文件名传递给一次rename
调用。
The substitution command is only supported by the Perl version of the rename
command.仅 Perl 版本的rename
命令支持替换命令。 You might have to install this version.您可能必须安装此版本。 See Get the Perl rename utility instead of the built-in rename请参阅获取 Perl 重命名实用程序而不是内置重命名
The substitution did not work in my test.替换在我的测试中不起作用。 I successfully used我成功使用
rename -v 's/(.*\/)?([^.]*)/$1\U$2/' file ...
The first group (.*\/)?
第一组(.*\/)?
optionally matches a sequence of characters with a trailing /
.可选地匹配带有尾随/
的字符序列。 This is used to copy the directory unchanged.这用于复制未更改的目录。
The second group ([^.]*)
matches a sequence of characters except .
第二组([^.]*)
匹配除 . 之外的字符序列.
. .
This is the file name part before the first dot (if any) which will be converted to uppercase.这是第一个点(如果有)之前的文件名部分,它将被转换为大写。 In case the file name has more than one extension, all will remain unchanged, eg如果文件名有多个扩展名,则全部保持不变,例如Path/To/Foo.Bar.Baz
-> Path/To/FOO.Bar.Baz
Path/To/Foo.Bar.Baz
/Foo.Bar.Baz -> Path/To/FOO.Bar.Baz
suggesting a trick with awk
that will generate all required mv
commands:建议使用awk
生成所有必需的mv
命令的技巧:
awk '{f=$0;split($NF,a,".");$NF=tolower(a[1])"."toupper(a[2]);print "mv "f" "$0}' FS=/ OFS=/ <<< $(find . -type f)
Inspect the result, and run all mv
commands together:检查结果,并一起运行所有mv
命令:
bash <<< $(awk '{f=$0;split($NF,a,".");$NF=tolower(a[1])"."toupper(a[2]);print "mv "f" "$0}' FS=/ OFS=/ <<< $(find . -type f))
awk
script script.awk
explanation awk
脚本script.awk
解释BEGIN { # preprocessing configuration
FS="/"; # set awk field separtor to /
OFS="/"; # set awk output field separtor to /
}
{ # for each line in input list
filePath = $0; # save the whole filePath in variable
# fileName is contained in last field $NF
# split fileName by "." to head: splitedFileNameArr[1] and tail: splitedFileNameArr[2]
split($NF,splitedFileNameArr,".");
# recreate fileName from lowercase(head) "." uppercase(tail)
$NF = tolower(splitedFileNameArr[1]) "." toupper(splitedFileNameArr[2]);
# generate a "mv" command from original filePath and regenerated fileName
print "mv "filePath" "$0;
}
mkdir {a1,B2}/{A1,b2} -p; touch {a1,B2}/{A1,b2}/{A,b}{b,C}.{c,D}{d,C}
find . -type f
./a1/A1/Ab.cC
./a1/A1/Ab.cd
./a1/A1/Ab.DC
./a1/A1/Ab.Dd
./B2/b2/AC.DC
./B2/b2/AC.Dd
.....
./B2/b2/bC.cd
./B2/b2/bC.DC
./B2/b2/bC.Dd
awk -f script.awk <<< $(find . -type f)
.....
mv ./a1/b2/Ab.cd ./a1/b2/ab.CD
mv ./a1/b2/Ab.DC ./a1/b2/ab.DC
mv ./a1/b2/Ab.Dd ./a1/b2/ab.DD
mv ./B2/A1/bC.Dd ./B2/A1/bc.DD
.....
mv ./B2/b2/bC.DC ./B2/b2/bc.DC
mv ./B2/b2/bC.Dd ./B2/b2/bc.DD
bash <<< $(awk -f script.awk <<< $(find . -type f))
find . -type f
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.