所以经过大量的搜索并试图解释别人的问题并解答我的需求后,我决定自问。
我正在尝试使用一个充满图像的目录结构,并将所有图像(无论扩展名)放在一个文件夹中。除此之外,我希望能够删除与过程中的某些文件名匹配的图像。我有一个find命令工作,为我输出所有的文件路径
find -type f -exec file -i -- {} + | grep -i image | sed 's/\:.*//'
但是如果我尝试使用它来复制文件,我就会遇到文件名中的空格。
cp `find -type f -exec file -i -- {} + | grep -i image | sed 's/\:.*//'` out/
我做错了什么,有更好的方法吗?
答案 0 :(得分:2)
需要注意的是,如果文件名称中包含换行符,则无效:
find . -type f -exec file -i -- {} + |
awk -vFS=: -vOFS=: '$NF ~ /image/{NF--;printf "%s\0", $0}' |
xargs -0 cp -t out/
(基于Jonathan Leffler的回答以及随后与他和@devnull的评论讨论。)
答案 1 :(得分:1)
如果没有文件名包含任何换行符,则find
命令可以正常工作。在宽范围内,grep
命令在相同的情况下可以正常工作。只要文件名中没有冒号,sed
命令就可以正常工作。但是,鉴于名称中有空格,使用$(...)
(命令替换,也用反向标记`...`
表示)是一种灾难。不幸的是,xargs
并不是解决方案的一部分;它默认在空格上分割。因为您必须在中间运行file
和grep
,所以您无法轻松使用-print0
选项(GNU)find
和-0
选项到(GNU)xargs
。
在某些方面,它很粗糙,但在很多方面,如果你编写一个可由find
调用的可执行shell脚本,这是最简单的:
#!/bin/bash
for file in "$@"
do
if file -i -- "$file" | grep -i -q "$file:.*image"
then cp "$file" out/
fi
done
这有点痛苦,因为它为每个名称分别调用file
和grep
,但它是可靠的。如果文件名包含换行符,则file
命令甚至是安全的; grep
可能不是。
如果该脚本名为'copyimage.sh',则find
命令变为:
find . -type f -exec ./copyimage.sh {} +
并且,考虑到编写grep
命令的方式,copyimage.sh
文件将不会被复制,即使其名称包含魔术词'image'。
答案 2 :(得分:0)
将find命令的结果传递给
xargs -l --replace cp "{}" out/
在Ubuntu 10.04上这对我有用的示例:
atomic@atomic-desktop:~/temp$ ls
img.png img space.png
atomic@atomic-desktop:~/temp$ mkdir out
atomic@atomic-desktop:~/temp$ find -type f -exec file -i \{\} \; | grep -i image | sed 's/\:.*//' | xargs -l --replace cp -v "{}" out/
`./img.png' -> `out/img.png'
`./img space.png' -> `out/img space.png'
atomic@atomic-desktop:~/temp$ ls out
img.png img space.png
atomic@atomic-desktop:~/temp$