Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在shell的一行中重命名多个文件 问题_Bash_Shell - Fatal编程技术网

Bash 在shell的一行中重命名多个文件 问题

Bash 在shell的一行中重命名多个文件 问题,bash,shell,Bash,Shell,目录中有以下格式的文件:*-foo-bar.txt 示例目录: $ ls *-* asdf-foo-bar.txt ghjk-foo-bar.txt l-foo-bar.txt tyui-foo-bar.txt bnm-foo-bar.txt iop-foo-bar.txt qwer-foo-bar.txt zxcv-foo-bar.txt $ ls *.txt asdf.txt bnm.txt ghjk.txt iop.txt l.txt qwer.txt

目录中有以下格式的文件:*-foo-bar.txt

示例目录:

$ ls *-*
asdf-foo-bar.txt  ghjk-foo-bar.txt  l-foo-bar.txt     tyui-foo-bar.txt
bnm-foo-bar.txt   iop-foo-bar.txt   qwer-foo-bar.txt  zxcv-foo-bar.txt
$ ls *.txt
asdf.txt  bnm.txt  ghjk.txt  iop.txt  l.txt  qwer.txt  tyui.txt  zxcv.txt
所需目录:

$ ls *-*
asdf-foo-bar.txt  ghjk-foo-bar.txt  l-foo-bar.txt     tyui-foo-bar.txt
bnm-foo-bar.txt   iop-foo-bar.txt   qwer-foo-bar.txt  zxcv-foo-bar.txt
$ ls *.txt
asdf.txt  bnm.txt  ghjk.txt  iop.txt  l.txt  qwer.txt  tyui.txt  zxcv.txt
解决方案1 我想到的第一个解决方案看起来有点像这个丑陋的黑客:

ls *-* | cut -d- -f1 | sed 's/.*/mv "\0-foo-bar.txt" "\0.txt"/' > rename.sh && sh rename.sh
上述解决方案会动态创建一个脚本来重命名文件。此解决方案还尝试解析
ls
的输出,这不是一件好事情

解决方案2 使用以下shell脚本可以更优雅地解决此问题:

for i in *-*
do
    mv "$i" "`echo $i | cut -f1 -d-`.txt"
done
上述解决方案使用循环重命名文件

问题: 有没有一种方法可以在一行中解决这个问题,这样我们就不必显式地编写循环脚本、生成脚本或调用新的或当前的shell(即避免sh、bash等命令)?

您尝试过该命令吗

例如:

rename 's/-foo-bar//' *-foo-bar.txt
如果没有,我将使用
find
sed
xargs

find . -maxdepth 1 -mindepth 1 -type f -name '*-foo-bar.txt' | sed 's/-foo-bar.txt//' | xargs -I{} mv {}-foo-bar.txt {}.txt

这并不能回答您的问题,但是--请注意,
$(echo$i | cut-f1-d-).txt
可以用
${i%%-*}.txt
的形式编写。此外,如果您担心解析
ls
不是一件好事,那么您还应该更好地使用双引号:
mv“$i”“${i%%-*}.txt”
。为什么要避免循环?在这种情况下,循环可能更有效,因为所有事情(除了
mv
)都可以由shell完成,而不是调用外部命令,如
find
sed
cut
等。@ruakh感谢您的评论。在最初的文章中,我指定文件名中没有空格。因此,我草率地使用了双引号。然而,现在我更新了我的帖子,以消除这一限制,支持更普遍的解决方案。谢谢你的
${i%%-*}.txt
提示。@Susanpal:我确实注意到你说没有空格;但是,双引号也会阻止解释shell元字符,如
*
[
(如果
$foo
设置为
*
,则
echo“$foo”
将打印星号,而
echo$foo
将打印当前目录中的文件列表。)外部命令管道比本机shell循环更昂贵。但无论您使用什么,您都必须重复调用
mv
,因为
mv
一次只能重命名一个文件。这基本上是Tim在下面的回答中所做的。
xargs
可以作为perl的脚本可作为用户运行。或者只对*-foo-bar.txt中的文件执行
;回显“mv'$file'${file%-foo-bar.txt}.txt'”;完成| sh
,但如果文件名中有单引号,则会中断。