Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.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
Linux 重命名目录中所有文件的bash脚本?_Linux_Bash_Shell - Fatal编程技术网

Linux 重命名目录中所有文件的bash脚本?

Linux 重命名目录中所有文件的bash脚本?,linux,bash,shell,Linux,Bash,Shell,我有一堆需要重命名的文件 file1.txt needs to be renamed to file1_file1.txt file2.avi needs to be renamed to file2_file2.avi 如您所见,我需要原始文件名的uuu 有很多这样的文件。用于文件*中的文件* 做 [-f“$file”]&&echo mv“$file”${file%%.*} 完成 递归思想 recurse(){ 对于“$1”/*”中的文件,请执行以下操作 如果[-d“$file”];则 递

我有一堆需要重命名的文件

file1.txt needs to be renamed to file1_file1.txt
file2.avi needs to be renamed to file2_file2.avi
如您所见,我需要原始文件名的uuu

有很多这样的文件。

用于文件*中的文件*
做
[-f“$file”]&&echo mv“$file”${file%%.*}
完成
递归思想

recurse(){
对于“$1”/*”中的文件,请执行以下操作
如果[-d“$file”];则
递归“$file”
其他的
#检查相关文件
#echo mv“$file”“${file%%.*}\u$file”
fi
完成
}
递归/path/to/files

我喜欢PERL cookbook的重命名脚本。它可能不是/bin/sh,但您可以像重命名一样执行正则表达式

/bin/sh方法是使用sed/cut/awk来更改for循环中的每个文件名。如果目录很大,则需要依赖xargs

#!/bin/bash
# Don't do this like I did:
# files=`ls ${1}`

for file in *.*
do
if [ -f $file ];
then
newname=${file%%.*}_${file}
mv $file $newname
fi
done

此工具不会重命名子目录,仅重命名常规文件。

应该提到专门为此而设计的
mmv
工具

find . -type f | while read FN; do
  BFN=$(basename "$FN")
  NFN=${BFN%.*}_${BFN}
  echo "$BFN -> $NFN"
  mv "$FN" "$NFN"
done
这里描述的是:


…以及备选方案。

对于您的特定情况,您希望使用
mmv
,如下所示:

pax> ll
total 0
drwxr-xr-x+ 2 allachan None 0 Dec 24 09:47 .
drwxrwxrwx+ 5 allachan None 0 Dec 24 09:39 ..
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file1.txt
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file2.avi

pax> mmv '*.*' '#1_#1.#2'

pax> ll
total 0
drwxr-xr-x+ 2 allachan None 0 Dec 24 09:47 .
drwxrwxrwx+ 5 allachan None 0 Dec 24 09:39 ..
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file1_file1.txt
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file2_file2.avi
您需要知道,通配符匹配不是贪婪的。这意味着文件
a.b.txt
将转换为
a_a.b.txt
,而不是
a.b_a.b.txt

mmv
程序是作为我的CygWin的一部分安装的,但我不得不这么做

sudo apt-get install mmv
在我的Ubuntu盒上下载。如果它不在您的标准发行版中,那么无论您使用的是什么包管理器,都希望它可用

如果出于某种原因,不允许您安装它,您将不得不使用另一个
bash
来解决其他答案中显示的
循环类型的解决方案。我自己更喜欢简洁的
mmv
,但您可能没有选择。

我使用prename(基于perl的),它包含在各种linux发行版中。它与正则表达式一起工作,所以可以说将所有img_x.jpg更改为IMAGE_x.jpg

prename 's/img_/IMAGE_/' img*jpg
您可以使用-n标志预览更改,而无需进行任何实际更改


到目前为止,所有答案都是:

  • 需要一些非便携工具吗
  • 使用包含空格或换行符的文件名进行可怕的中断
  • 不是递归的,即不下降到子目录
  • 这两个脚本解决了所有这些问题

    bash2.X/3.X
    #/bin/bash
    而IFS=read-r-d$'\0'文件;做
    dirname=“${file%/*}/”
    basename=“${file:${#dirname}}”
    echo mv“$file”“$dirname${basename%.*}
    

    done<您的文件名中是否有空格、引号、换行符或其他笨拙的字符?之前有许多问题几乎都是重复的,包括更多问题,请参阅:我想您的意思是:文件中的文件*;执行mv“$file”`echo“${file%%.*};done@Mark,为目录添加一个测试并不费多大力气。@ghostdog:我同意,shell扩展是处理糟糕文件名的最佳方法,但您建议如何在bash 2.x/3.x中递归地执行此操作?因为您的代码不会遍历到子目录。@Siegex。正如我在编辑中所说明的,您可以纯粹使用shell进行递归。这只是一个想法,并不是完整的解决方案,但你明白了。我认为askvictor在这方面比你强多了,伙计。是的,他太匆忙了,没有从一堆人中说出主要工具的名字。我诚实地独立地找到了相同的链接,搜索我心目中的工具;既然我觉得我的答案更有用,我就不说了。你能告诉我默认安装了mmv的是哪个平台吗?是的:Rock Linux包括mmv;但这并没有多大帮助,因为它是一个相当模糊的发行版。但是,Red Hat/Fedora/CentOS、Debian/Ubuntu和Gentoo都提供了易于安装的软件包。千万不要使用
    ls
    的输出进行解析。请参阅,了解为什么ISI如果您不分析文件名,则仍然可以分析其他字段的ls。这是什么意思
    ${file%%.*}
    ?@benjamin button:“%%”从$file结尾删除了patern“.*”。我测试了您的bash2.x/3.x解决方案。我的输出-->mv./file2.txt wu./file2.txt示例使用shell扩展仍然是最好的方法,即使对于文件中的换行符也是如此names@levislevis85:修复了路径名的问题,但它确实适用于换行,只是
    echo
    让你有了不同的想法。你能想出一个解决方案来解决所有这些问题是件好事。。。但是请注意,这个问题是专门针对Linux上1目录中的文件提出的,文件名没有任何异常。@Code Duck:添加递归功能是一项微不足道的任务,我们永远不应该对文件名做任何假设,始终将其视为包含换行符或其他污点。第二种情况是,如果有人添加了一个会严重破坏您的脚本的脚本,并且不知道会发生什么。这不会处理带有空格或换行符的文件名。也不能处理子目录中的文件,因为它会将子目录中的文件移动到顶级目录中。