所以,我有以下结构:
.
..
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,如何将文件的扩展名更改为第二个命令?
我如何重命名文件,以便我可以只有一个扩展名。
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
)。
这也可以使用xargs
和sed
来更改文件扩展名。
ls | grep \.png$ | sed 'p;s/\.png/\.jpg/' | xargs -n2 mv
您可以打印原始文件名以及您想要的文件名。然后让xargs在move命令中使用这两个参数。对于单行,我还添加了一个grep来过滤掉任何不是* .png文件的东西。
迟到了,但这里是你如何用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来重命名该文件。
要清除错误,请尝试使用rename
实用程序。查看联机帮助页以获取详细信息
在您的情况下,如果您的当前目录设置正确,您将执行rename '.png.jpg' '.jpg' ./*
。
既然你有convert
可用,我假设你也有mogrify
(imagemagick
套件)。每当我想这样做时,我将文件复制到另一个目录并使用mogrify
代替。我通常只需要调整大小,但如果你改变图像格式,mogrify
将处理文件名(使用适当的文件名制作新文件)。
你会用它作为mogrify -format jpg -resize [size] ./*.png
。我不确定没有几何参数的-resize
应该做什么。它没有记录,也不适用于我的机器。
正如Tim Pote推论的那样,我认为你不能让xargs单独处理文件名和扩展名。
我在这个派对上迟到了大约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
这有三件事:
编辑
我现在意识到这是最复杂的方法。可以简单地使用rename命令。
rename 's/svg\.png/.png/' *
我的解决方案类似于许多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
经过对类似任务的一些调查,这里是我的代码:
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%避免失去任何东西我的尝试来自: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
find ./xx -name "*.png" -print0 |sed 's/.png$//g'|xargs -0 -I% mv %.png %.jpg