Рекурсивно искать файлы с определенным расширением

Я пытаюсь найти все файлы с определенным расширением в каталоге и его подкаталогах с помощью моего bash (последний выпуск Ubuntu LTS).

Это то, что написано в файле script:

#!/bin/bash

directory="/home/flip/Desktop"
suffix="in"

browsefolders ()
  for i in "$1"/*; 
  do
    echo "dir :$directory"
    echo "filename: $i"
    #   echo ${i#*.}
    extension=`echo "$i" | cut -d'.' -f2`
    echo "Erweiterung $extension"
    if     [ -f "$i" ]; then        

        if [ $extension == $suffix ]; then
            echo "$i ends with $in"

        else
            echo "$i does NOT end with $in"
        fi
    elif [ -d "$i" ]; then  
    browsefolders "$i"
    fi
  done
}
browsefolders  "$directory"

К сожалению, когда я запускаю этот script в терминале, он говорит:

[: 29: in: unexpected operator

$extension вместо 'in')

Что происходит здесь, где ошибка? Но эта фигурная скобка

Ответ 1

find $directory -type f -name "*.in"

немного короче, чем все это (и безопаснее - имеет дело с пробелами в именах файлов и именах каталогов).

Вероятно, ваш script не подходит для записей, у которых нет имени . в имени, что делает $extension пустым.

Ответ 2

find {directory} -type f -name '*.extension'

Пример для поиска всех CSV файлов в текущем каталоге и его подкаталогах

find . -type f -name '*.csv'

Ответ 3

Синтаксис, который я использую, немного отличается от того, что предложил @Matt:

find $directory -type f -name \*.in

(это еще одно нажатие клавиши).

Ответ 4

Без использования find:

du -a $directory | awk '{print $2}' | grep '\.in$'

Ответ 5

  • Там { отсутствует browsefolders ()
  • Все $in должны быть $suffix
  • Строка с cut получает только среднюю часть front.middle.extension. Вы должны прочитать руководство по работе с оболочкой ${varname%%pattern} и друзей.

Я предполагаю, что вы выполняете это как упражнение в сценариях оболочки, в противном случае предлагаемое решение find - это путь.

Чтобы проверить правильность синтаксиса оболочки, без запуска script, используйте sh -n scriptname.

Ответ 6

Чтобы найти все pom.xml файлы в вашем текущем каталоге и распечатать их, вы можете использовать:

find . -name 'pom.xml' -print

Ответ 7

Хотя использование команды find может быть полезно здесь, сама оболочка предоставляет опции для выполнения этого требования без каких-либо сторонних инструментов. Оболочка bash предоставляет расширенную опцию поддержки glob, с помощью которой вы можете получить имена файлов по рекурсивным путям, которые соответствуют нужным расширениям.

Расширенной опцией является extglob который необходимо установить с shopt опции shopt как shopt ниже. Опции активируются с поддержкой -s и отключаются с -u флага -u. Кроме того, вы можете использовать несколько опций больше, например, nullglob в котором непревзойденный nullglob, заменяется набором нулевых слов. И globstar который позволяет проходить через все каталоги

shopt -s extglob nullglob globstar

Теперь все, что вам нужно сделать, это сформировать выражение glob для включения файлов с определенным расширением, которые вы можете сделать, как показано ниже. Мы используем массив для заполнения результатов глоба, потому что при правильном цитировании и расширении имена файлов со специальными символами останутся нетронутыми и не сломаются из-за вставки слова -s оболочкой.

Например, чтобы перечислить все файлы *.csv в рекурсивных путях

fileList=(**/*.csv)

Опция ** состоит в том, чтобы проходить через подпапки, а *.csv - расширение glob, чтобы включить любой файл упомянутых расширений. Теперь для печати реальных файлов, просто сделайте

printf '%s\n' "${fileList[@]}"

Использование массива и правильное раскрытие в кавычках - правильный путь при использовании в сценариях оболочки, но для интерактивного использования вы можете просто использовать ls с выражением glob как

ls -1 -- **/*.csv

Это вполне может быть расширено для соответствия нескольким файлам, т.е. файлам, заканчивающимся несколькими расширениями (то есть аналогично добавлению нескольких флагов в команде find). Например, рассмотрим случай получения всех файлов рекурсивных изображений, например с расширениями *.gif, *.png и *.jpg, все, что вам нужно, это

ls -1 -- **/+(*.jpg|*.gif|*.png)

Это вполне может быть расширено, чтобы иметь отрицательные результаты также. С тем же синтаксисом можно использовать результаты glob для исключения файлов определенного типа. Предположим, вы хотите исключить имена файлов с расширениями выше, вы можете сделать

excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"

Конструкция !() - это операция отрицания, которая не включает в себя расширения файлов, перечисленные внутри и | является оператором чередования, который используется в библиотеке расширенных регулярных выражений для сопоставления ИЛИ глобанов.

Обратите внимание, что эта расширенная поддержка glob недоступна в оболочке POSIX bourne и является чисто специфической для последних версий bash. Так что, если вы рассматриваете переносимость сценариев, работающих в POSIX и оболочках bash, этот вариант будет неправильным.

Ответ 8

find $directory -type f -name "*.in"|grep $substring

Ответ 9

for file in "${LOCATION_VAR}"/*.zip
do
  echo "$file"
done 

Ответ 10

find "$PWD" -type f -name "*.in"