bash Linux shell脚本查找和重命名文件以删除后缀?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14163922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Linux shell script to find and rename files to remove suffix?
提问by boltup_im_coding
I have some files named like this:
我有一些这样命名的文件:
file1.c.keep.apple
file1.c.keep.apple
file2.c.keep.apple
file2.c.keep.apple
I am trying to write a shell script so that I pass in the suffix as an argument (in this case, apple) and it will rename all of the files removing the .keep.apple.
我正在尝试编写一个 shell 脚本,以便我将后缀作为参数传递(在本例中为apple),它将重命名所有删除.keep.apple.
Example execution:
示例执行:
script.sh apple
script.sh apple
results in the files above being renamed to
导致上面的文件被重命名为
file1.c
文件1.c
file2.c
文件2.c
So far, I have
到目前为止,我有
#! /bin/sh
find . -type f -name \'*.keep.\' -print0 | xargs -0 rename 's/\(.keep.*)$//'
and the files do not get renamed. I know the findportion is correct. I am thinking the regex on my rename is wrong. How can I get the script working the way I want?
并且文件不会被重命名。我知道这find部分是正确的。我认为我重命名的正则表达式是错误的。我怎样才能让脚本按照我想要的方式工作?
回答by Ignacio Vazquez-Abrams
I know the
findportion is correct
我知道这
find部分是正确的
Except it isn't.
除了它不是。
find . -type f -name "*.keep." -print0 | ...
回答by jesse_galley
Updated, try this perhaps:
更新了,试试这个吧:
#!/bin/bash
SUFFIX=;
find . -type f -name "*keep.${SUFFIX}" | while read -r file;
do
nfile=`echo $file | sed "s/\.keep\.${SUFFIX}//g"`;
mv "$file" "$nfile" 2>/dev/null;
done
here it is running:
它正在运行:
jgalley@jgalley-debian:/test5$ cat replace.sh
#!/bin/bash
SUFFIX=;
find . -type f -name "*keep.${SUFFIX}" | while read -r file;
do
nfile=`echo $file | sed "s/\.keep\.${SUFFIX}//g"`;
mv "$file" "$nfile" 2>/dev/null;
done
jgalley@jgalley-debian:/test5$ find .
.
./-filewithadash.keep.apple
./dir1
./dir1/file
./dir1/file2.keep.orange
./dir2
./dir2/file2
./file with spaces
./file.keep.orange
./file.keep.somethingelse.apple
./file.orange
./replace.sh
jgalley@jgalley-debian:/test5$ ./replace.sh apple
jgalley@jgalley-debian:/test5$ find .
.
./-filewithadash
./dir1
./dir1/file
./dir1/file2.keep.orange
./dir2
./dir2/file2
./file with spaces
./file.keep.orange
./file.keep.somethingelse.apple
./file.orange
./replace.sh
jgalley@jgalley-debian:/test5$
回答by Uwe Kleine-K?nig
I'd say you need:
我会说你需要:
find . -type f -name "*.keep." -print0 | xargs -0 rename "s/\.keep\.$//"
Note the following limitations:
请注意以下限制:
- rename might not be available everywhere.
find -print0andxargs -0are GNU extensions which might not be available on all Unixes.- if your first parameter contains characters that are special for regexes the result might not what you want. (e.g.
yourscript "a*e")
- 重命名可能并非随处可用。
find -print0并且xargs -0是 GNU 扩展,可能并非在所有 Unix 上都可用。- 如果您的第一个参数包含正则表达式的特殊字符,则结果可能不是您想要的。(例如
yourscript "a*e")
回答by Josh Cartwright
If you can assume bash, and a version of bash greater then 4 (with globstar support), here is a clean bash-only solution:
如果您可以假设 bash 和大于 4 的 bash 版本(有 globstar 支持),这里是一个干净的 bash-only 解决方案:
#!/usr/bin/env bash
(($#)) || exit 1
shopt -s globstar nullglob
for f in **/*.keep.""; do
mv -- "$f" "${f%.keep.}"
done
Alternatively, here is a solution using findand a while readloop (assumes GNU or BSD find):
或者,这里是使用find和while read循环的解决方案(假设 GNU 或 BSD 找到):
find . -type f -name "*.keep." -print0 | while IFS= read -r -d '' f; do
mv -- "$f" "${f%.keep.}"
done
See http://mywiki.wooledge.org/BashFAQ/030for more details on this solution.
有关此解决方案的更多详细信息,请参阅http://mywiki.wooledge.org/BashFAQ/030。
Also, you can implement what you are trying to do using findwith -exec:
此外,你可以实现你试图用做find有-exec:
find . -type f -name "*.keep." -exec sh -c 'mv -- "" "${2%.keep.}"' _ "" {} ';'
回答by F. Hauri
Shorter:
更短:
shopt -s globstar
rename 's/\.keep\.apple$//' **/*.keep.apple
(require perl)
(需要 perl)
回答by yaccz
If you can simply glob the files, you can do just
如果你可以简单地对文件进行 glob,你可以只做
rename '.keep.apple' '' *
otherwise you would replace the *with the find+ xargsyou already have.
否则你会用你已经拥有*的find+替换xargs。
Note in this by renameis meant renamefrom util-linux. On some systems it is installed like rename.ulinstead of rename.
注意这里的rename意思是rename从util-linux。在某些系统上,它的安装方式类似于rename.ul而不是rename.
回答by Satish
How about this?
这个怎么样?
[spatel@us tmp]$ x=aa.bb.cc
[spatel@us tmp]$ y=${x%.cc}
[spatel@us tmp]$ echo $y
aa.bb
[spatel@us tmp]$ x=aa.bb.cc
[spatel@us tmp]$ y=${x%.bb.cc}
[spatel@us tmp]$ echo $y
aa

