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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 04:09:42  来源:igfitidea点击:

Linux shell script to find and rename files to remove suffix?

linuxbashshell

提问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 -print0and xargs -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):

或者,这里是使用findwhile 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意思是renameutil-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