例如,report jpg 将显示所有名为 something.jpg 的文件。这是我正在研究的代码,包括我的问题。
function report {
x=`ls *.$1`
num=`ls *.$1 | wc -l`
# Question 1:
# Want to use variable for x to get
# num, but num=$($x | wc -l) didn't work for this purpose.
echo There are $num $1 files
if [ $num -lt 10 ]; then
# Question 2:
# for this part, I want to use "find . -name '*.$1'
# with delimiter . to extract filename from its extension
# and display them (Also maybe need to use while or for loop)
fi
}
report jpg
report html
答案1
具体回答你的问题:
Q1. 该表达式的$x | wc -l
意思是“运行命令$x
并将结果通过管道传输到wc -l
”。要通过管道传输内容您可以使用$x
或(使用 bashwc
num=`echo "$x" | wc -l`
这里是字符串)num=`wc -l <<< "$x"`
。
但是,“反引号”形式的命令替换已被弃用 - 最好养成使用$( ... )
ie的习惯
num=$(wc -l <<< "$x")
请注意,如果任何文件名包含换行符(Linux 中允许),这将给出错误的计数。
Q2. 在 中find . -name '*.$1'
,单引号(又称“硬引号”)'*.$1'
将阻止 的扩展,$1
因此find
将搜索以 结尾的文件名$1
。要允许 的扩展,$1
同时防止 的过早扩展*.
,请使用双引号(又称“软引号”),即"*.$1"
您可能希望将搜索限制在顶级目录中,而不是下降到子目录中(否则结果将与从中获得的计数不一致wc
):
find . -maxdepth 1 -name "*.$1"
然而,下面是我如何做的 - 假设有一个bash
shell:
report() {
shopt -s nullglob
local ext="$1"
set -- *."$ext"
printf 'There are %d %s files' $# "$ext"
if (( $# > 0 && $# < 10 )); then
printf '\t%s\n' "$@"
fi
}
这避免了Bash 陷阱 #1(解析 的输出,ls
而不是使用 shell glob)并使用 shell 的set
内置命令将匹配的文件名读入$@
位置参数数组。这样,您可以使用$#
来明确地计算文件数量(即使它们包含换行符 - 管道到ls
会wc
给出错误的计数),并且无需使用单独的find
命令来再次获取匹配的名称。
如果你想显示文件名没有扩展,你可以用它替换,$@
从数组的每个元素中删除最短的尾随子字符串匹配,使用printf
${@%.*}
.*
参数扩展。
尽管我选择使用(( ... ))
算术构造来测试文件数量,但使用 POSIX[ $# -le 10 ]
或[ $# -lt 10 ]
您喜欢的其他方法也没有错。额外的$# > 0
测试只是为了在没有给定扩展名的文件时保持输出美观。
您可以使用扩展数组轻松扩展该函数以接受多个扩展:
function report {
shopt -s nullglob
local exts=( "$@" )
for ext in "${exts[@]}"; do
set -- *."$ext"
printf 'There are %d %s files' $# "$ext"
if (( $# > 0 && $# < 10 )); then
printf ': \n'
printf '\t%s\n' "$@"
else
printf '.\n'
fi
done
}
使用示例:
$ report txt jpg foo
There are 71 txt files.
There are 4 jpg files:
b.jpg
foo.jpg
inv_logpolar.jpg
logpolar.jpg
There are 0 foo files.
答案2
#!/bin/bash
report(){
local -a n=(*.$1)
echo "There are #${#n[@]} files in '$PWD' with extension '$1'."
if (( ${#n[@]} < 10 )); then
find . -maxdepth 1 -type f -name "*.$1" -printf %f\\n | sed -e 's/\.[^.]*$//'
fi
}
report $1
用法:./script.sh jpg