创建一个函数,使用 bash 中的分隔符从多个文件名中提取文件名

创建一个函数,使用 bash 中的分隔符从多个文件名中提取文件名

例如,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或(使用 bashwcnum=`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"

然而,下面是我如何做的 - 假设有一个bashshell:

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内置命令将匹配的文件名读入$@位置参数数组。这样,您可以使用$#来明确地计算文件数量(即使它们包含换行符 - 管道到lswc给出错误的计数),并且无需使用单独的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

相关内容