Создайте функцию для извлечения имен файлов из нескольких имен файлов, используя разделитель в bash

Например, отчет jpg будет отображать все файлы, которые называются что-то.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
2
задан 27 September 2019 в 19:49

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

1
ответ дан 23 October 2019 в 10:25

Отвечать на Ваши вопросы конкретно:

Q1. средства выражения $x | wc -l "выполняют команду $x и передают результаты по каналу к wc -l". Для передачи по каналу эти содержание из $x к wc Вы могли использовать num=`echo "$x" | wc -l` или (использование удара здесь строка ) num=`wc -l <<< "$x"`.

Однако форма "обратной галочки" замены команды удерживается от использования - лучше для вырабатывания привычку использования $( ... ) т.е.

num=$(wc -l <<< "$x")

Примечание, что это даст неправильное количество, если какие-либо имена файлов будут содержать символы новой строки (которому их позволяют в Linux).

Q2. В [1 113], одинарные кавычки (иначе 'трудно заключает в кавычки') приблизительно [1 114] предотвратят расширение [1 115], таким образом find будет искать имена файлов, заканчивающиеся буквально в [1 117]. Для разрешения расширения [1 118] при предотвращении преждевременного расширения [1 119] используйте двойные кавычки (иначе "мягкие кавычки"), т.е. "*.$1"

Вы, вероятно, захотите ограничить поиск каталогом верхнего уровня вместо того, чтобы убывать в подкаталоги (еще, результаты будут несовместимы с количеством, полученным от [1 121]):

    find . -maxdepth 1 -name "*.$1"
<час>

Однако , вот то, как я сделал бы это - принятие bash оболочка:

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 (анализирующий вывод [1 123] вместо того, чтобы использовать шарик оболочки) и использует оболочку set встроенный для чтения соответствия именам файлов в $@ позиционный массив параметров. Таким образом, можно использовать $# для подсчета количества файлов однозначно (даже если они содержат новые строки - где передача по каналу ls к [1 128] дала бы неправильное количество), и нет никакой потребности использовать отдельное find команда для получения имен соответствия снова и снова.

, Если Вы хотите отобразить имена файлов без [1 142] расширение, можно заменить $@ в printf с [1 132], который удаляет самую короткую запаздывающую подстроку, соответствующую .* от каждого элемента массива с помощью [1 140] расширение параметра .

, Хотя я принял решение использовать (( ... )) арифметическая конструкция для тестирования количества файлов, нет ничего неправильно с использованием 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.
3
ответ дан 23 October 2019 в 10:25