循环查找已添加到数组中的命令结果?带空格的文件名视为 2 个条目

循环查找已添加到数组中的命令结果?带空格的文件名视为 2 个条目

我创建了以下代码。最后,我想单独处理数组中的每个文件,但在此代码中的某处我没有包含双引号,因此中间带有空格的文件名被视为数组中的 2 个条目:

#!/bin/bash

EXT=(sh mkv txt)

EXT_OPTS=()
# Now build the find command from the array
for i in "${EXT[@]}"; do
    EXT_OPTS+=( -o -iname "*.$i" )
done

# remove the first thing in EXT_OPTS
EXT_OPTS=( "${EXT_OPTS[@]:1}" )

# Modify to add things to ignore:
EXT_OPTS=( '(' "${EXT_OPTS[@]}" ')' ! '(' -iname "*test*" -o -iname "*sample*" ')' )

#echo "${EXT_OPTS[@]}"

searchResults=($(find . -type f "${EXT_OPTS[@]}"))

#echo "$searchResults"

for R in "${searchResults[@]}"; do
    echo "$R"
    sleep 1
done

所以我得到的结果是:

./Find2.sh
./untitled
2.sh
./countFiles.sh
./unrar.sh
./untitled
3.sh
./untitled
4.sh
./clearRAM.sh
./bash_test.sh
./Test_Log.txt
./untitled.txt
./Find.txt
./findTestscript.sh
./untitled.sh
./unrarTest.sh
./Test.sh
./Find.sh
./Test_Log
copy.txt
./untitled
5.sh
./IF2.sh

例如,无标题 5.sh 已作为 2 个条目添加到数组中。我在哪里忘记添加“s

干杯

编辑建议的编辑:

#!/bin/bash

EXT=(sh mkv txt)

EXT_OPTS=()
# Now build the find command from the array
for i in "${EXT[@]}"; do
    EXT_OPTS+=( -o -iname "*.$i" )
done

# remove the first thing in EXT_OPTS
EXT_OPTS=( "${EXT_OPTS[@]:1}" )

# Modify to add things to ignore:
#EXT_OPTS=( "${EXT_OPTS[@]:-1}" )
EXT_OPTS=( '(' "${EXT_OPTS[@]}" ')' ! '(' -iname "*x0r*" -o -iname "*torrent*" ')' )

#echo "${EXT_OPTS[@]}"

#searchResults=($(find . -type f "${EXT_OPTS[@]}"))

#echo "$searchResults"

#for R in "${searchResults[@]}"; do
#   echo "$R"
#   sleep 1
#done


find . -type f "${EXT_OPTS[@]}" -exec sh -c '
    for pathname do
        printf "%s\n" "$pathname"
        sleep 1
    done' sh {} +

现在生产:

./Find2.sh
./untitled 2.sh
./countFiles.sh
./unrar.sh
./untitled 3.sh
./Find3.sh
./untitled 4.sh
./clearRAM.sh
./bash_test.sh
./Test_Log.txt
./untitled.txt
./Find.txt
./findTestscript.sh
./untitled.sh
./unrarTest.sh
./Test.sh
./Find.sh
./Test_Log copy.txt
./untitled 5.sh
./IF2.sh
./Find4.sh

答案1

不,您不应该解析 的输出find。如果您想对find找到的路径名执行某些操作,则应该从内部执行此操作find

find ...stuff... -exec sh -c '
    for pathname do
        printf "%s\n" "$pathname"
        sleep 1
    done' sh {} +

在这里,find将使用批量找到的路径名调用内联 shell 脚本(该脚本可能会被调用多次)。find充当内部脚本的一种路径名生成器。

另一种方法是使用中间的-print0路径名来输出,然后使用知道如何读取以 null 结尾的路径名的工具来读取它们。 \0nul 字符\0是唯一不允许成为 Unix 路径名一部分的字符,因此这是将它们传递给另一个工具的唯一安全方法。

有关的:

答案2

对于较新版本bash(> 4.4 IIRC),mapfile内置允许您指定空分隔符 - 然后您可以find ... print0按照中的建议使用拘萨罗南达的回答例如

mapfile -t -d '' searchResults < <(find . -type f "${EXT_OPTS[@]}" -print0)

如果这不是一个选择,那么一个更慢更丑的方法将是这样的

while IFS= read -r -d '' f; do 
  searchResults+=("$f")
done < <(find . -type f "${EXT_OPTS[@]}" -print0)

参见相关内容bash:find 到 select 的空白安全过程使用

相关内容