【问题标题】:How to copy files name/path containing spaces in unix?如何在unix中复制包含空格的文件名/路径?
【发布时间】:2020-01-25 08:37:32
【问题描述】:

我的目标是搜索包含模式的文件并将其复制到文件夹中。这些文件可能在一个文件夹的多个文件夹中可用(例如 /home/abc/logs/ ....)。一些文件名和文件夹带有空格字符,包括空格。我正在尝试将找到的结果分配给一个变量并复制它。但结果是“参数列表太长”

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

【问题讨论】:

  • @tripleee:我看不出这两个问题都是骗人的。单独引用不会保留grep 输出中参数分隔符和真实空格之间的区别。如果我错过了骗子的哪一部分回答了这个问题的问题,请证明。 (请注意,cp "$LOGS_TO_COPY" temp/ 立即显而易见的答案是错误的。)
  • 添加了另一个副本。你好像在找grep -rl "$pattern" "$LOG_FILE_PATH" | xargs cp -t temp/
  • @tripleee 我对我列出的任何选项都很满意。该链接至少是相关的,尽管不是直接的解决方案(grep 具有--null 选项至少需要是评论)。鉴于产生正确的解决方案显然不像看起来那么简单,我将投票重新开放,尽管link 对于解释原因和一般性非常有用。 (我的另一条评论因不正确而被删除。)

标签: bash shell unix cp file-copying


【解决方案1】:

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

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 $'\0' -r file; do cp "$file" temp/; done

或者,您可以使用xargs 代替while+read

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

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

declare -a files
while IFS= read -d $'\0' -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 命令的解决方案可能不会。

【讨论】:

  • 感谢您的解决方案。在这里,当我运行命令时 --> grep -Hrn "$pattern" "$LOG_FILE_PATH" 找到的文件数是 22584(在我的情况下),当我运行你的命令(第一个带有 while 的命令)时,找到的文件数是 329 所以我觉得很多文件丢失了
  • 正如我所说,grep -Hrn 显示匹配的每一行。然后您使用cut 切断行和内容,因此如果有 100 行匹配,您将有 100 次相同的文件名。我没有考虑过,但这也是你的命令行太长的原因。 grep -l 只会显示每个文件名一次。尝试将 grep -lr ... | wc -l 与您列表的重复数据版本进行比较:grep -Hrn ... | cut ... | sort | uniq | wc -l
  • 这里粘贴得到的结果 grep -lr "$pattern" "$LOG_FILE_PATH" |而 IFS= 读取 -r 文件;做 cp "$file" .;完成了| wc -l 330 ############## grep -Hrn "$pattern" "$LOG_FILE_PATH"|排序 |独特 | wc -l 22598 ############### grep -Hrn "$pattern" "$LOG_FILE_PATH" | wc -l 22598
  • 您错过了剪切排序 uniq 步骤,以查看您获得了多少 不同 文件。
猜你喜欢
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 2013-04-07
  • 2012-09-30
  • 2018-04-20
  • 1970-01-01
  • 2017-01-13
  • 2010-09-28
相关资源
最近更新 更多