有人能告诉我为什么以下命令无法运行:
find ./assign/*.c -exec cp ./assign2 {} \;
当我执行以下操作时(实际运行)有什么区别:
find ./assign -type f -name *.c -exec cp {} ./assign2 \;
答案1
find ./assign/*.c -exec cp ./assign2 {} \;
shell 在执行 find 之前就已经扩展了通配符 ( *
)。假设在assign 目录中有两个文件 source1.c 和 source2.c,那么上面的代码相当于
find ./assign/source1.c ./assign/source2.c -exec cp ./assign2 {} \;
这当然是有效的,并且意味着你只想对这些特定文件执行某些操作。例如,你可以写
find ./assign/*.c -name '*2*'
结果大致相当于ls ./assign/*.c | grep 2
或ls ./assign/*2*.c
。
请注意,如果您不想让 shell 扩展通配符,则需要将它们放在引号中:
find "./assign/*.c"
但是,这样做会失败,因为 find 按字面意思来处理路径名(没有任何通配符扩展),所以它看起来字面上地对于名为*.c
(是的,这是一个有效的文件名)。
至于第一个表达式的第二部分(exec cp ./assign2 {} \;
)。显然,这是一个拼写错误,因为 cp 命令试图将assign2 目录复制到第二个参数。假设您在assign 目录中有文件source1.c 和source2.c,则命令的结果将等同于
cp assign2/ ./assign/source1.c
cp assign2/ ./assign/source2.c
这可能不是您想要的(而且它会失败,因为您无法将目录复制到文件名)。
现在,对于第二个表达式,因为这里也有一个问题:
find ./assign -type f -name *.c -exec cp {} ./assign2 \;
这将有效仅有的.c
如果当前目录中没有带扩展名的文件。否则,shell 将扩展*.c
。假设您有以下文件:
./master.c
./assign/source1.c
./assign/source2.c
上述命令行将首先被 shell 扩展为
find ./assign -type f -name master.c -exec cp {} ./assign2 \;
这将失败,因为在assign/目录中没有文件master.c。相反,使用
find ./assign -type f -name "*.c" -exec cp {} ./assign2 \;
无论如何,除非你在 ./assign 下有一个复杂的目录结构或以 结尾的目录.c
,否则我宁愿只
cp ./assign/*.c ./assign2
答案2
对于“查找”,您需要按顺序指定:
- 在哪里搜索(./assign)
- 文档类型(-type f 又称文件),但这是可选的
- 文档名称(-name *.c,即每个扩展名为 .c 的文件),这不是可选的
然后,您告诉“find”,在搜索之后,它必须运行特定的命令(-exec),并且您发出的两个命令中“cp”的语法都是正确的,但由于第一个命令中“find”的语法不正确,所以第一个命令将不会运行。
顺便说一句,我认为在找到所有 .c 文件后,将目录 ./assign2 复制到实际查找 ({}) 没有任何意义,而应该反过来。也就是说,在我看来,即使语法正确,第一行中的“cp”命令也不会执行任何操作。