找到多少个文件?
how many files find found?
我正在编写一个脚本,如果我正在搜索的文件存在于多个位置,我想在其中出错,并告诉用户位置(查找结果)。所以我找到了这样的:
file_location=$(find $dir -name $file -print)
我认为查看是否在多个位置找到该文件应该很简单,但我必须不匹配 find 用于分隔结果的内容(有时看起来像 space,换行符其他)。因此,我不想匹配它,而是想看看 $file_location.
中的 $file 之后是否有任何字符
我正在检查
echo "$file_location" | grep -q "${file}."; then
这仍然不起作用。所以我想我不在乎我使用什么,除了我想捕获 $file_location 作为查找的结果,然后检查它。能推荐个好方法吗?
我推荐使用:
find . -name blong.txt -print0
这告诉 find
将其输出与空 [=12=]
字符连接在一起。使 awk
与 -F
标志或 xargs
与 -0
标志一起使用变得更容易。
如果您在find
命令中指定全名,则名称匹配将是唯一的。也就是说,如果您输入 find -name "hello.txt"
,则只会找到名为 hello.txt
的文件。
你可以做的是
find $dir -name $file -printf '.'
^^^^^^^^^^^
这将打印与找到的匹配项一样多的 .
。然后,要查看使用此名称找到了多少文件,只需计算输出的点数即可。
尝试:
N=0
for i in `find $dir -name $file -printf '. '`
do
N=$((N+1))
done
echo $N
found=$(find "$dir" -name "$file" -ls)
count=$(wc -l <<< "$found")
if [ "$count" -gt 1 ]
then
echo "I found more than one:"
echo "$found"
fi
对于找到的零个匹配项,您仍然会收到 1,因为 shell strips 带有 $()
运算符的尾随换行符的不透明方式,所以实际上,一行输出和零行输出最终都是一行。有关再次用作输入时自动附加换行符的演示,请参阅 xxd <<< ""
。一个简单的规避方法是在字符串的开头添加一个假的换行符,这样就不会出现空字符串:found=$(echo; find …)
,然后从行数中减去一个。
编辑:我在对 -ls
的回答中更改了 -printf "%p\n"
的用法,它执行正确的换行引用。否则带有换行符的文件名会弄乱计数。
如果你想避免 eols 等错误,可以像下面这样
files=()
while IFS= read -d $'[=10=]' -r match; do
files+=("$match")
done < <(find "$dir" -name "$file" -print0)
(${#files[@]} > 1) && printf '%s\n' "${files[@]}"
或在bash 4+
shopt -s globstar dotglob
files=("$dir"/**/"$file")
((${#files[@]} > 1)) && printf '%s\n' "${files[@]}"
如果您是 运行 一个新的 (4.0+) bash,它可以自己进行递归 globbing,那么这里不需要 find
;只需将 glob 结果直接加载到 shell 数组中,并检查其长度:
shopt -s nullglob globstar # enable recursive globbing, and null results
file_locations=( "$dir"/**/"$file" )
echo "${#file_locations[@]} files named $file found under $dir; they are:"
printf ' %q\n' "${file_locations[@]}"
如果你不想惹nullglob
,那么:
shopt -s globstar # enable recursive globbing
file_locations=( "$dir"/**/"$file" )
# without nullglob, a failed match will return the glob expression itself
# to test for this, see if our first entry exists
if [[ -e ${file_locations[0]} ]]; then
echo "No instances of $file found under $dir"
else
echo "${#file_locations[@]} files named $file found under $dir; they are:"
printf ' %q\n' "${file_locations[@]}"
fi
您仍然可以使用数组明确读取旧版本 bash 上的 find
结果;与更幼稚的方法不同,即使文件或目录名称包含文字换行符,这也会起作用:
file_locations=( )
while IFS= read -r -d '' filename; do
file_locations+=( "$filename" )
done < <(find "$dir" -type f -name "$file" -print0)
echo "${#file_locations[@]} files named $file found under $dir; they are:"
printf ' %q\n' "${file_locations[@]}"
我正在编写一个脚本,如果我正在搜索的文件存在于多个位置,我想在其中出错,并告诉用户位置(查找结果)。所以我找到了这样的:
file_location=$(find $dir -name $file -print)
我认为查看是否在多个位置找到该文件应该很简单,但我必须不匹配 find 用于分隔结果的内容(有时看起来像 space,换行符其他)。因此,我不想匹配它,而是想看看 $file_location.
中的 $file 之后是否有任何字符我正在检查
echo "$file_location" | grep -q "${file}."; then
这仍然不起作用。所以我想我不在乎我使用什么,除了我想捕获 $file_location 作为查找的结果,然后检查它。能推荐个好方法吗?
我推荐使用:
find . -name blong.txt -print0
这告诉 find
将其输出与空 [=12=]
字符连接在一起。使 awk
与 -F
标志或 xargs
与 -0
标志一起使用变得更容易。
如果您在find
命令中指定全名,则名称匹配将是唯一的。也就是说,如果您输入 find -name "hello.txt"
,则只会找到名为 hello.txt
的文件。
你可以做的是
find $dir -name $file -printf '.'
^^^^^^^^^^^
这将打印与找到的匹配项一样多的 .
。然后,要查看使用此名称找到了多少文件,只需计算输出的点数即可。
尝试:
N=0
for i in `find $dir -name $file -printf '. '`
do
N=$((N+1))
done
echo $N
found=$(find "$dir" -name "$file" -ls)
count=$(wc -l <<< "$found")
if [ "$count" -gt 1 ]
then
echo "I found more than one:"
echo "$found"
fi
对于找到的零个匹配项,您仍然会收到 1,因为 shell strips 带有 $()
运算符的尾随换行符的不透明方式,所以实际上,一行输出和零行输出最终都是一行。有关再次用作输入时自动附加换行符的演示,请参阅 xxd <<< ""
。一个简单的规避方法是在字符串的开头添加一个假的换行符,这样就不会出现空字符串:found=$(echo; find …)
,然后从行数中减去一个。
编辑:我在对 -ls
的回答中更改了 -printf "%p\n"
的用法,它执行正确的换行引用。否则带有换行符的文件名会弄乱计数。
如果你想避免 eols 等错误,可以像下面这样
files=()
while IFS= read -d $'[=10=]' -r match; do
files+=("$match")
done < <(find "$dir" -name "$file" -print0)
(${#files[@]} > 1) && printf '%s\n' "${files[@]}"
或在bash 4+
shopt -s globstar dotglob
files=("$dir"/**/"$file")
((${#files[@]} > 1)) && printf '%s\n' "${files[@]}"
如果您是 运行 一个新的 (4.0+) bash,它可以自己进行递归 globbing,那么这里不需要 find
;只需将 glob 结果直接加载到 shell 数组中,并检查其长度:
shopt -s nullglob globstar # enable recursive globbing, and null results
file_locations=( "$dir"/**/"$file" )
echo "${#file_locations[@]} files named $file found under $dir; they are:"
printf ' %q\n' "${file_locations[@]}"
如果你不想惹nullglob
,那么:
shopt -s globstar # enable recursive globbing
file_locations=( "$dir"/**/"$file" )
# without nullglob, a failed match will return the glob expression itself
# to test for this, see if our first entry exists
if [[ -e ${file_locations[0]} ]]; then
echo "No instances of $file found under $dir"
else
echo "${#file_locations[@]} files named $file found under $dir; they are:"
printf ' %q\n' "${file_locations[@]}"
fi
您仍然可以使用数组明确读取旧版本 bash 上的 find
结果;与更幼稚的方法不同,即使文件或目录名称包含文字换行符,这也会起作用:
file_locations=( )
while IFS= read -r -d '' filename; do
file_locations+=( "$filename" )
done < <(find "$dir" -type f -name "$file" -print0)
echo "${#file_locations[@]} files named $file found under $dir; they are:"
printf ' %q\n' "${file_locations[@]}"