带有空格的文件名 for 循环,查找命令

Ubu*_*ser 48 bash scripts find

我有一个脚本,可以将多个子文件夹和存档中的所有文件搜索到 tar。我的脚本是

for FILE in `find . -type f  -name '*.*'`
  do
if [[ ! -f archive.tar ]]; then

  tar -cpf archive.tar $FILE
else 
  tar -upf archive.tar $FILE 
fi
done
Run Code Online (Sandbox Code Playgroud)

find 命令给了我以下输出

find . -type f  -iname '*.*'
./F1/F1-2013-03-19 160413.csv
./F1/F1-2013-03-19 164411.csv
./F1-FAILED/F2/F1-2013-03-19 154412.csv
./F1-FAILED/F3/F1-2011-10-02 212910.csv
./F1-ARCHIVE/F1-2012-06-30 004408.csv
./F1-ARCHIVE/F1-2012-05-08 190408.csv
Run Code Online (Sandbox Code Playgroud)

但是FILE变量只存储路径的第一部分./F1/F1-2013-03-19,然后是下一部分160413.csv

我尝试使用readwhile 循环,

while read `find . -type f  -iname '*.*'`;   do ls $REPLY; done
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误

bash: read: `./F1/F1-2013-03-19': not a valid identifier
Run Code Online (Sandbox Code Playgroud)

任何人都可以建议另一种方式吗?

更新

正如下面的答案中所建议的,我更新了脚本

#!/bin/bash

INPUT_DIR=/usr/local/F1
cd $INPUT_DIR
for FILE in "$(find  . -type f -iname '*.*')"
do
archive=archive.tar

        if [ -f $archive ]; then
        tar uvf $archive "$FILE"
        else
        tar -cvf $archive "$FILE"
        fi
done
Run Code Online (Sandbox Code Playgroud)

我得到的输出是

./test.sh
tar: ./F1/F1-2013-03-19 160413.csv\n./F1/F1-2013-03-19 164411.csv\n./F1/F1-2013-03-19 153413.csv\n./F1/F1-2013-03-19 154412.csv\n./F1/F1-2012-09-10 113409.csv\n./F1/F1-2013-03-19 152411.csv\n./.tar\n./F1-FAILED/F3/F1-2013-03-19 154412.csv\n./F1-FAILED/F3/F1-2013-03-19 170411.csv\n./F1-FAILED/F3/F1-2012-09-10 113409.csv\n./F1-FAILED/F2/F1-2011-10-03 113911.csv\n./F1-FAILED/F2/F1-2011-10-02 165908.csv\n./F1-FAILED/F2/F1-2011-10-02 212910.csv\n./F1-ARCHIVE/F1-2012-06-30 004408.csv\n./F1-ARCHIVE/F1-2011-08-17 133905.csv\n./F1-ARCHIVE/F1-2012-10-21 154410.csv\n./F1-ARCHIVE/F1-2012-05-08 190408.csv: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
Run Code Online (Sandbox Code Playgroud)

Tho*_*hor 55

在这里使用forwithfind是错误的方法,例如参见这篇关于您正在打开的蠕虫罐头的文章。

推荐的方法是使用findwhileread描述在这里。下面是一个应该适合你的例子:

find . -type f -name '*.*' -print0 | 
while IFS= read -r -d '' file; do
    printf '%s\n' "$file"
done
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以用空 ( \0) 字符分隔文件名,这意味着空格和其他特殊字符的变化不会导致问题。

为了使用find找到的文件更新存档,您可以将其输出直接传递给tar

find . -type f -name '*.*' -printf '%p\0' | 
tar --null -uf archive.tar -T -
Run Code Online (Sandbox Code Playgroud)

请注意,您不必区分存档是否存在,tar会明智地处理它。还要注意使用-printfhere 以避免./在存档中包含该位。


kir*_*iri 18

尝试for像这样引用循环:

for FILE in "`find . -type f  -name '*.*'`"   # note the quotation marks
Run Code Online (Sandbox Code Playgroud)

没有引号,bash 根本不能很好地处理空格和换行符 ( \n)...

也尝试设置

IFS=$'\n'
Run Code Online (Sandbox Code Playgroud)

  • +1 为 $IFS。这描述了分隔符。 (2认同)

小智 17

这有效并且更简单:

find . -name '<pattern>' | while read LINE; do echo "$LINE" ; done
Run Code Online (Sandbox Code Playgroud)

此答案归功于 Rupa ( https://github.com/rupa/z )。

  • 简单的。作品。伟大的。 (2认同)