如何在 unix 中复制包含空格的文件 name/path?

How to copy files name/path containing spaces in unix?

我的目标是搜索包含模式的文件并将其复制到文件夹中。这些文件可能在一个文件夹中的许多文件夹中可用(比如 /home/abc/logs/ ....)。一些文件名和文件夹带有空格字符,包括空格。我正在尝试将找到的结果分配给一个变量并复制它。但结果是 "Argument list too long"

Linux 服务器

pattern="somesttring" ;
LOG_FILE_PATH="/path/to/logs/"
LOGS_TO_COPY=$(grep -Hrn "$pattern" "$LOG_FILE_PATH" | cut -d: -f1)
cp $LOGS_TO_COPY temp #temp is folder to which i have to copy 

我收到以下错误:

cp $LOGS_TO_COPY temp/
-bash: /bin/cp: Argument list too long

不要将它存储在变量中,至少不是普通的字符串变量。字符串变量无法保持每个参数内部的 space 与分隔它们的 space 之间的差异。

grep -lr "$pattern" "$LOG_FILE_PATH" | while IFS= read -r file; do cp "$file" temp/; done

另请注意,您不需要剪切 grep 结果,因为 -l 标志只为您提供文件名,正是您想要的。 -H 是默认值,因此不需要,如果您只是想将其切断,则 -n 是不必要的。

如果您的文件名称中包含换行符,这将不起作用。作为解决方案,您可以告诉 grep(和 read)使用 NUL 作为分隔符。

grep -lr --null "$pattern" "$LOG_FILE_PATH" | while IFS= read -d $'[=11=]' -r file; do cp "$file" temp/; done

或者,您可以使用 xargs 而不是 while+read:

grep -lr --null "$pattern" "$LOG_FILE_PATH" | xargs --null -I {} cp {} temp/

如果您必须将其存储在变量中,请使用与上述相同的模式将其存储到数组变量中。这样就不需要 space 作为参数分隔符。

declare -a files
while IFS= read -d $'[=13=]' -r file; do files+=("$file"); done < <(grep -lr --null "$pattern" "$LOG_FILE_PATH")
cp "${files[@]}" temp/

这是另一种方法(尽管如果文件名包含换行符,这将不起作用,因为 mapfile 不支持更改分隔符):

mapfile -t files < <(grep -lr "$pattern" "$LOG_FILE_PATH")
cp "${files[@]}" temp/

如果要复制的文件数量很大,whilexargs 解决方案仍然有效,但那些简单地将整个数组放入一个 cp 命令的方法可能没有。