批量重命名命令行和Xargs中的文件

问题描述 投票:22回答:9

所以,我有以下结构:

.
..
a.png
b.png 
c.png

我跑了一个命令来调整它们的大小

ls | xargs -I xx convert xx -resize xx.jpg

现在我的目录看起来像这样

.
..
a.png.jpg
a.png
b.png.jpg
b.png
c.png.jpg
c.png

第一个问题是,我如何重命名文件,以便我可以只有一个扩展名。不是两个。 (基本上,我该如何清理原来的错误)? 第二个问题是,在将来,使用xargs,如何将文件的扩展名更改为第二个命令?

linux shell unix command-line xargs
9个回答
20
投票

我如何重命名文件,以便我可以只有一个扩展名。

cd dir/with/messedup/files

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

在将来,使用xargs,如何更改文件的扩展名类似于第二个命令?

据我所知,这是不可能完成的。最好的方法是使用带有参数替换的for循环,就像上面那样:

for file in *.png; do
  convert "$file" -resize "${file%.png}.jpg"
done

如果您要转换的子目录中有文件,则可以将find传递给while read循环:

find . -type f -name '*.png' |
while read file; do
  convert "$file" -resize "${file%.png}.jpg"
done

注意:在shell脚本中使用bad idea的输出通常被认为是ls。虽然你的例子可能运行良好,但有很多例子没有。例如,如果你的文件名碰巧有新行(unix允许),那么ls可能不会为你逃脱。 (这实际上取决于你的实现,这是不在脚本中使用ls的另一个原因;它的行为在一个盒子到另一个盒子之间变化很大。)如果你在while-read循环中使用find,或者你会得到更一致的结果。在for循环中文件globbing(例如*.png)。


51
投票

这也可以使用xargssed来更改文件扩展名。

ls | grep \.png$ | sed 'p;s/\.png/\.jpg/' | xargs -n2 mv

您可以打印原始文件名以及您想要的文件名。然后让xargs在move命令中使用这两个参数。对于单行,我还添加了一个grep来过滤掉任何不是* .png文件的东西。


11
投票

迟到了,但这里是你如何用xargs重命名文件。假设您有一堆名为fileN.svg.png的文件,并且您想将它们命名为fileN.png,其中N可以是一系列整数:

ls *.svg.png | xargs basename -s .svg.png | xargs -I {} mv {}.svg.png {}.png

第一个xargs使用basename去掉.svg和.png以获得一个正确的filenameN。第二个xargs接收该裸名称并使用replacement来重命名该文件。


6
投票

要清除错误,请尝试使用rename实用程序。查看联机帮助页以获取详细信息

在您的情况下,如果您的当前目录设置正确,您将执行rename '.png.jpg' '.jpg' ./*

既然你有convert可用,我假设你也有mogrifyimagemagick套件)。每当我想这样做时,我将文件复制到另一个目录并使用mogrify代替。我通常只需要调整大小,但如果你改变图像格式,mogrify将处理文件名(使用适当的文件名制作新文件)。

你会用它作为mogrify -format jpg -resize [size] ./*.png。我不确定没有几何参数的-resize应该做什么。它没有记录,也不适用于我的机器。

正如Tim Pote推论的那样,我认为你不能让xargs单独处理文件名和扩展名。


3
投票

我在这个派对上迟到了大约3年,我遇到了类似的问题,我自己也搞清楚了。我有一个使用inkscape转换的png文件列表,因为ImageMagick的svg支持很差。

我最初通过以下方式转换它们:

find . -name "*.svg" -exec inkscape {} --export-png={}.png

这当然导致了如上所述的相同问题。

file1.svg
file1.svg.png
file2.svg
file2.svg.png
file3.svg
file3.svg.png
file4.svg
file4.svg.png

我想将* .svg.png重命名为* .png,这就是我最后的结果......

find . -name "*.svg.png" -print0 | sed 's/.svg.png//g' | xargs -0 -I namePrefix mv namePrefix.svg.png namePrefix.png

这有三件事:

  1. 在此目录中找到名为* .svg.png的文件,-print0将打印到标准输出
  2. sed修改标准输出,基本上交换.svg.png没什么,所以我得到:file1 / file2 / file3 / file4
  3. xargs -0从sed获取数据,-I引用扩展名为w / o的文件名,然后将原始文件名mv改为新文件名。 namePrefix这个词并不特别,只是想说清楚。

编辑

我现在意识到这是最复杂的方法。可以简单地使用rename命令。

rename 's/svg\.png/.png/' *

1
投票

我的解决方案类似于许多xarg解决方案,特别类似于Schleis。

这里的区别在于使用匹配引用的完整正则表达式操作,以及正确忽略不匹配文件的sed命令,因此您无需预先过滤列表。

对于包含空格和shell元的文件,这也是安全的。

将替换中的\2更改为任何所需的扩展名。

ls |
sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty \1\2"/;T;p' |
xargs -n 2 mv

说明

-n arg告诉sed默认情况下不打印任何内容,T命令说如果先前的s命令没有替换,则跳到脚本末尾,p命令打印模式空间(仅当s命令匹配时才会命中)。

替换中的&是对原始文件名匹配内容的引用。

如果我们用mv替换命令中的bash -c 'echo "run($#) $@"' bash,那么我们可以看到调用mv的次数,以及参数count和value:

$ ls |
  sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty \1\2"/;T;p' |
  xargs -n 2 bash -c 'echo "run($#) $@"' bash
run(2) Rick.and.Morty.S03E02.720p.HDTV.x264-BATV.mkv Rick and Morty S03E02.mkv
run(2) Rick.and.Morty.S03E03.720p.HDTV.x264-BATV.mkv Rick and Morty S03E03.mkv
run(2) Rick.and.Morty.S03E04.720p.HDTV.x264-BATV.mkv Rick and Morty S03E04.mkv
run(2) Rick.and.Morty.S03E05.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E05.mkv
run(2) Rick.and.Morty.S03E06.720p.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E06.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E07.720p.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E07.mkv
run(2) Rick.and.Morty.S03E08.720p.HDTV.x264-BATV.mkv Rick and Morty S03E08.mkv
run(2) Rick.and.Morty.S03E09.720p.HDTV.x264-BATV.mkv Rick and Morty S03E09.mkv
run(2) Rick.and.Morty.S03E10.720p.HDTV.x264-BATV.mkv Rick and Morty S03E10.mkv

1
投票

经过对类似任务的一些调查,这里是我的代码:

find . -maxdepth 1 -name '*.png' -print0 | sed 's/.png//g' | xargs -0 -I% -n 1 -P 8 convert -quality 100 %.png %.jpg

推理:

  • 重命名不会压缩文件(因此使用convert而不是mv
  • ls \.png$ | xargs不会处理路径/文件名中的空格
  • find .将在子文件夹中搜索,因此请使用-maxdepth 1
  • convert不使用可用的CPU,所以-P8(或-P other
  • 最后没有sed'g'不会替换所有文件(只有一个)
  • sed 's/.png//g'不会留下任何延期(基地名也可以工作,但没有在-print0之后)
  • parallel - 可能更好的解决方案,但不适用于我的Ubuntu 18.04 bash 4.4
  • %是最小的替代符号(与{} xx namePrefix相比)
  • -n2参数对xargs有好处但是没有正确使用-print0(在n之后采取和通过的xargs条目数量)
  • -quality 100默认魔法质量是92(这很好),这里100%避免失去任何东西

0
投票

我的尝试来自:https://www.tecmint.com/linux-image-conversion-tools/

ls -1 *.png | xargs -n 1 bash -c 'convert "$0" "${0%.png}.jpg"'

使用并行

parallel convert '{}' '{.}.jpg' ::: *.png

-1
投票

find ./xx -name "*.png" -print0 |sed 's/.png$//g'|xargs -0 -I% mv %.png %.jpg

© www.soinside.com 2019 - 2024. All rights reserved.