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

时间:2012-06-10 20:13:26

标签: linux shell unix command-line xargs

所以,我有以下结构:

.
..
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,如何将文件的扩展名更改为第二个命令?

9 个答案:

答案 0 :(得分:50)

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

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

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

答案 1 :(得分:19)

  

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

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脚本中使用ls的输出通常被视为bad idea。虽然你的例子可能运行良好,但有很多例子没有。例如,如果你的文件名碰巧有新行(unix允许),ls可能不会逃避那些。 (这实际上取决于您的实现,这是在脚本中不使用ls的另一个原因;它的行为在一个框与下一个框之间变化很大。)如果使用{{1},您将获得更一致的结果在for循环中的while-read循环或文件通配(例如find)。

答案 2 :(得分:10)

迟到了,但这里有你如何使用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来重命名该文件。

答案 3 :(得分:6)

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

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

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

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

正如Tim Pote所说,我认为你不能让xargs单独处理文件名和扩展名。

答案 4 :(得分: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引用没有扩展名的文件名,然后将原始文件名mv改为新文件名。 namePrefix这个词并不是什么特别的,只是想说清楚。
  4. 修改

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

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

答案 5 :(得分: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告诉我们默认情况下不打印任何内容,T命令说如果前一个s命令没有替换,则跳到脚本末尾, p命令打印模式空间(仅在s命令匹配时才会命中)。

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

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

$ 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

答案 6 :(得分: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一起正常使用(nxargs之后要通过的条目数) / li>
  • -quality 100的默认魔法质量为92(可以),此处100%可以避免丢失任何东西

答案 7 :(得分: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

答案 8 :(得分:-1)

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