路径名中的空格给Bash中的Find带来麻烦。任何*简单*解决方案?

时间:2010-10-10 01:04:42

标签: bash find

有没有办法更改以下字符串,以便在存在空格的文件/文件夹时不会出现任何问题?

files=`find ~/$folder -name "*@*" -type f`

我更喜欢是否有一个解决方案,不必涉及我的代码的其他部分,但这一行代码,因为一切似乎工作正常,除了这个小细节。

由于

编辑:以下是更详细的代码:

abc=( $(find "$pasta" -name "$ficheiro_original@*" -type f) )
abc_length=${#abc[@]}

5 个答案:

答案 0 :(得分:10)

如果您稍后在脚本中没有使用这些文件名,只需迭代它们并即时处理。

find ~/$folder -name "*@*" -type f | while read -r FILE
do
  echo "do you stuff"
done

否则,您可以设置IFS

IFS=$'\n'
files=$(find ~/$folder -name "*@*" -type f)

更新

$ IFS=$'\n'
$ a=($(find . -type f ))
$ echo ${#a[@]}
14

答案 1 :(得分:2)

如果您需要名称中可能包含空格的文件列表,则几乎必须将它们存储为数组,而不仅仅是字符串。使用以下内容创建数组:

saveIFS="$IFS"; IFS=$'\n'; files=( $(find ~/"$folder" -name "*@*" -type f) ); IFS="$saveIFS"

然后你将不得不修改脚本的其余部分以将文件用作数组而不是字符串,并且它(和其他文件名)应始终使用双引号以防止空格被误认为是分隔符。例如,您当前正在使用$files的任何地方,请将其替换为"${files[@]}"

ls "${files[@]}"
for f in "${files[@]}"; do
    ls "$f"
done
echo "found ${#files[@]} files" 

答案 2 :(得分:2)

您必须进行一些更改,但要处理任意名称,请考虑使用GNU查找选项-print0等。

find ~/$folder -name "*@*" -type f -print0 |
while read -d '^@' file
do
    echo "<<$file>>"
done

(表示为'^@'的单字节实际上是ASCII NUL('\ 0';输入 Control-V 控制移 - @

find ~/$folder -name "*@*" -type f -print0 |
while read -d '' file
do
    echo "<<$file>>"
done

分隔符的空字符串表示'使用零字节,ASCII NUL作为分隔符',适用于解析“find ... -print0”输出。 (感谢Dennis Williamson提示。)

这允许您读取任意名称。您应该使用bash数组来保存名称,但这意味着脚本中的某些更改。

(鉴于只有空格必须担心的评论响应,这可能是过度的,尽管使用read来处理具有名称的行是操作的关键部分,并且使用数组可能会使生活更简单。)

答案 3 :(得分:1)

这是另一种不改变其余代码的方法:

# files=($(find))
eval "files=($(find -printf '"%h/%f" '))"

for f in "${files[@]}"; do
  echo "$f"
done

它很脏,对于带有特殊字符的文件名不起作用,例如"。它使用eval来评估Bash数组的字符串和-printf的{​​{1}}以形成该字符串。

我个人更喜欢改变find,仅限FYI。

答案 4 :(得分:1)

要将包含空格的文件名读入Bash数组变量,您也可以使用“read”内置命令:

printf '%q\n' "$IFS"

IFS=$'\n' read -r -d "" -a abc <<< "$(find ~/$folder -name "*@*" -type f)"
IFS=$'\n' read -r -d "" -a abc < <(find ~/$folder -name "*@*" -type f)  # alternative

abc_length=${#abc[@]}

for ((i=1; i <= ${#abc[@]}; i++)); do echo "$i:  ${abc[i-1]}"; done

printf '%q\n' "$IFS"

请注意,新设置的IFS变量的范围仅限于执行read命令(原始IFS变量保持原样)。