Joh*_*ton 4 command-line bash find
我一直试图让这个工作一段时间。我想搜索文件列表,然后将它们全部复制到某个路径。
如果我单独运行该命令,则它的工作方式如下:
find <path> -name 'file1' -exec cp '{}' <path2> \;
Run Code Online (Sandbox Code Playgroud)
但是我一直无法在 for 循环中运行它。
#this works
for f in file1 file2 file3...; do find <path> -name "$f" \; done;
#none of these work (this code tries to find and copy the files named file and list from the path)
for f in file1 file2 file3...; do find <path> -name "$f" -exec cp '{}' <path2> \; done;
for f in file1 file2 file3...; do find <path> -name "$f" -exec cp {} <path2> \; done;
Run Code Online (Sandbox Code Playgroud)
我尝试了其他一些不太可能奏效的东西。代码引用中的第一行卡住了,其他人即使没有卡住也不会复制任何内容。
搜索后,我无法在 for 循环中使用 exec 运行任何内容,此时我不确定该怎么做。
我已经通过搜索文件并将结果记录到另一个文件,然后在 for 循环中单独运行副本解决了眼前的问题,但我仍然想知道如何做到这一点。
两个问题:
for f in some_file不迭代 的内容some_file,只是迭代或获取文字字符串some_file。为了克服这个忘记for循环迭代文件内容的问题,使用正确实现的while构造。
'$f'在这种情况下,将变量放在单引号内时不会扩展。要使您的原始想法发挥作用,请使用双引号。
将这些放在一起,假设文件名在file_list文件内以换行符分隔:
while IFS= read -r f; do
find /path1 -name "$f" -exec cp '{}' /path2 \;
done <file_list
Run Code Online (Sandbox Code Playgroud)
或者,如果您知道文件将在该/path1目录中,而不是在它的任何子目录下,您可以只使用数组来获取文件名,并cp直接使用 (GNU) ,再次假设文件名内部有换行符file_list:
(
IFS=$'\n'
files=( $(<file_list) )
cp -t /path2 "${files[@]}"
)
Run Code Online (Sandbox Code Playgroud)
在大量文件的情况下,最好cp单独迭代而不是转储到数组中:
while IFS= read -r f; do cp -- "$f" /path2; done <file_list
Run Code Online (Sandbox Code Playgroud)
如果file1 file2 file3 ...直接在for构造中有像 eg 这样的文件列表,那么只使用双引号就可以了:
for f in file1 file2 file3; do
find /path1 -name "$f" -exec cp '{}' /path2 \;
done
Run Code Online (Sandbox Code Playgroud)
现在,cp如果所有文件都不在任何子目录中,您也可以直接在此处使用:
cp -t /path2 file1 file2 file3
Run Code Online (Sandbox Code Playgroud)
或者您可以提供静态绝对或相对路径,以防您只想cp用于处理任何子目录下的任何文件。
您澄清说您的文件列表不是文本文件,而是您希望使用find. 你提到这对你有用:
for f in file1 file2 file3 ... ; do find <path> -name "$f" \; done;
Run Code Online (Sandbox Code Playgroud)
大概您的意思是您从该命令中获得了预期的文件列表。
然后你说这不起作用:
for f in file1 file2 file3 ... ; do find <path> -name "$f" -exec cp '{}' <path2> \; done
Run Code Online (Sandbox Code Playgroud)
大概你的意思是前面列出的文件没有复制到<path2>. 我不确定您遇到了什么错误,但正如所写的那样,我希望该命令像这样挂起:
$for f in file1 file2 file3 ... ; do find <path> -name "$f" -exec cp '{}' <path2> \; done
>
Run Code Online (Sandbox Code Playgroud)
等待失踪;。假设你纠正了这个问题,我想不出你的命令肯定会失败的任何其他明显原因。你应该能够管理
for f in file1 file2 file3 ... ; do find <path> -name "$f" -exec cp '{}' <path2> \; ; done
Run Code Online (Sandbox Code Playgroud)
但是我建议使用-t标志来指定目录。我要感谢大卫·福斯特的这个评论,我觉得表演的最佳形式的cp或mv调用使用find。它也将拒绝覆盖重复文件。
for f in file1 file2 file3; do find /path/to/search -name "$f" -exec cp -vt /path/to/destination -- {} + ; done
Run Code Online (Sandbox Code Playgroud)
-v 详细点 - 告诉我们正在做什么-t 使用指定的目录作为目标-- 不接受任何进一步的选择+如果有多个匹配项(在您的情况下这不太可能,因为for它将为文件列表中的每个项目运行一次,但每个名称可能有多个匹配的文件),然后构造一个参数列表cp而不是cp多次运行;在 shell 中分隔命令。for循环的形式是
for var in things; do command "$var"; done
Run Code Online (Sandbox Code Playgroud)
如果没有看到;before done,bash 将等待;或中断信号。