使用终端linux mint找到并复制目录中的所有图像,试图理解语法

时间:2014-06-16 15:03:25

标签: linux terminal grep find mint

OS Linux Mint

就像标题最后说的那样,我希望找到并复制目录中的所有图像。

我找到了:

查找目录中的所有jpg(或JPG)文件并将其复制到文件夹/ home / joachim / neu2:

find . -iname \*.jpg -print0 | xargs -I{} -0 cp -v {} /home/joachim/neu2

查找目录中的所有图像文件:

find . -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image' 

我的问题首先是,我真的不懂语法。有人可以解释一下代码吗?

其次,有人可以连接这两个代码来生成满足我想要的代码;)

提前问候和感谢!

4 个答案:

答案 0 :(得分:18)

首先,了解管道“|” links命令管道输出第一个到第二个作为参数。你的两个shell代码都将find命令的输出管道输出到其他命令(grep和xargs)。让我们一个接一个地看看这些命令:

第一个命令:查找

find是一个“在目录层次结构中搜索文件”的程序(这是find的手册页中的解释)。语法是(在这种情况下)

find <search directory> <search pattern> <action>

在这两种情况下,搜索目录都是。 (这是当前目录)。请注意,它不仅搜索当前目录,还搜索其所有子目录(目录层次结构)。

搜索模式接受选项-name(意味着它搜索其名称与作为此选项的参数给出的模式匹配的文件)或-iname(与名称相同但区分大小写)等。

动作模式可以是-print0(打印确切的文件名,包括它在给定搜索目录中的位置,即文件的相对或绝对路径)或-exec(在文件上执行给定的命令,命令以“;”结束,“{}”的每个实例都被文件名替换。

即第一个shell代码(第一部分,管道左侧)

find . -iname \*.jpg -print0 

在当前目录层次结构中搜索结尾为“.jpg”的所有文件,并打印其路径和名称。第二部分(第一部分)

find . -name '*' -exec file {} \; 

查找当前目录层次结构中的所有文件并执行

file <filename>

他们。文件是另一个确定并打印文件类型的命令(有关详细信息,请查看手册页,man文件)。

第二个命令:xargs

xargs是一个“从标准输入构建和执行命令行”(man xargs)的命令,即来自通过管道传输到xargs的查找输出。在这种情况下,它构建和执行的命令

cp -v {} /home/joachim/neu2"

选项-I {}定义替换字符串,即命令中的每个{}实例都将由它从文件中获取的输入(即文件名)替换。选项-0定义输入项不是由空格或换行符终止(分隔),而是仅由空字符终止。当使用和标准方式处理查找输出作为xargs输入时,这似乎是必要的。

构建和执行的命令当然是带有选项-v(详细)的复制命令,它将从find获取的每个文件名复制到目录。

第三个命令:grep

grep过滤其输入,仅提供与特定输出模式匹配的那些行或字符串。选项-o告诉grep只打印匹配的字符串,而不是整行(参见man grep),-P告诉它将以下模式解释为perl regexp模式。在perl正则表达式中,^是行的开头,。+是任意字符串,这个任意字符串后面应该跟一个冒号,一个空格,一些字母数字字符(在perl正则表达式中表示为\ w +)一个空格和字符串“图片”。本质上,这个grep命令过滤文件输出,只输出作为图像文件的文件名。 (例如,请阅读perl正则表达式:http://www.comp.leeds.ac.uk/Perl/matching.html

您真正想要的命令

现在你要做的是(1)获取第二个shell命令的输出(列出图像文件),(2)将其输入相应的表格,然后(3)将其输入到xargs命令中第一个shell命令行(然后构建并执行您想要的复制命令)。所以这次我们有一个带有两个管道的三个(实际上是四个)阶段shell命令。不是问题。我们已经有阶段(1)和(3)(虽然在阶段(3)我们需要省略-0选项,因为输入不再是find输出;我们需要它将换行视为项目分隔符)。

阶段(2)仍然缺失。我建议使用cut命令。剪切更改字符串py将它们拆分为不同的字段(由原始字符串中的分隔符分隔),然后可以重新排列。我将选择“:”作为分隔符(这将结束grep输出中的文件名,选项-d':')并告诉它只给我们第一个字段(选项-f1,essentialls:仅打印文件名,而不是在“:”之后的部分,即阶段(2)将是

cut -d':' -f1

然后你想要的整个命令就是:

find . -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image' | cut -d':' -f1 | xargs -I{} cp -v {} /home/joachim/neu2

请注意,您可以在此处找到所有手册页:http://www.linuxmanpages.com

答案 1 :(得分:0)

我发现了一个只使用awk执行该命令的命令:

find . -name '*' -exec file {} \; | 
awk '{
    if ($3=="image"){
        print substr($1, 0, length($1)-1);
        system("cp " substr($1, 0, length($1)-1) " /home/joachim/neu2" )
    }   
}'

需要substr($ 1,0,length($ 1)-1),因为在第一列文件中返回name;

答案 2 :(得分:0)

以上答案非常好。但如果它是一个巨大的目录,可能需要更长的时间 如果你已经知道你的文件扩展名

,这是一个较短的版本
 find . -name \*.jpg | cut -d':' -f1 | xargs -I{} cp --parents -v {} ~/testimage/

答案 3 :(得分:0)

这是另一种很有魅力的方法。 它增加了 EPOCH 时间以防止覆盖同名文件。

cd /media/myhome/'Local station'/
find . -path ./jpg -prune -o -type f -iname '*.jpg' -exec sh -c '
for file do
   newname="${file##*/}"
   newname="${newname%.jpg}"
   mv -T -- "$file" "/media/myhome/Local station/jpg/$newname-$(date +%s).jpg"
done
' find-sh {} +
cd  ~/

它是由 Kamil 在 this post here 设计的。