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

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

Вот что написано в файле скрипта:

#!/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"

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

[: 29: in: unexpected operator

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

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

384
задан 14.03.2020, 16:07

10 ответов

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

du -a $directory | awk '{print $2}' | grep '\.in
12
ответ дан 14.03.2020, 16:07
  • 1
    @younce мы отправили его сегодня:/let' s видят то, что наблюдательный совет думает об этом решении. Приложение won' t отказывают, если они изменят API, он не будет просто больше поворачивать намеченный путь. – epologee 08.11.2019, 05:19
  1. После browsefolders ()
  2. отсутствует {. Все $in должны быть $suffix
  3. . Строка с cut дает вам только среднюю часть front.middle.extension. Вы должны прочитать руководство по оболочке на ${varname%%pattern} и у друзей.

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

Для проверки правильности синтаксиса оболочки без запуска сценария используйте sh -n scriptname.

10
ответ дан 14.03.2020, 16:07
  • 1
    Вполне хорошее обходное решение, спасибо за предложение:) – epologee 08.11.2019, 05:19

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

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

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

58
ответ дан 14.03.2020, 16:08
  • 1
    @epologee You' приветствие ре. Я думаю, что Вы хотите сделать, все еще достижимо, но you' ll должны создать пользовательское, содержащее контроллер представления, чтобы сделать это. Посмотрите части о контроллерах представления однорангового узла, имеющих проблемы в ссылке, которую я отправил. Кажется, что Вы могли обойти то ограничение с некоторым усилием. – A. R. Younce 08.11.2019, 05:20
  • 2
    Matt' s сценарий также won' t работают если there' s файл с .in расширением в текущем каталоге, в то время как Ваш все еще работал бы. См. stackoverflow.com/questions/5927369/… – Shnatsel 14.03.2020, 16:08
find $directory -type f -name "*.in"|grep $substring
1
ответ дан 14.03.2020, 16:09
  • 1
    Короче говоря, этот won' t работа. shouldAutorotateToInterfaceOrientation предназначен, чтобы быть названным платформой, и не вручную. Это действительно только возвращает булево значение что использование платформы для информирования вращения представления. – A. R. Younce 08.11.2019, 05:20
for file in "${LOCATION_VAR}"/*.zip
do
  echo "$file"
done 
0
ответ дан 14.03.2020, 16:09
  • 1
    Когда я записал это, у меня был код в shouldAutorotate, который изменил интерфейс на основе ориентации. Я don' t знают, было ли это лучшим способом сделать вещи, но it' s, что я сделал в то время. – B_. 08.11.2019, 05:21
find "$PWD" -type f -name "*.in"
3
ответ дан 14.03.2020, 16:09
  • 1
    Можно ли уточнить? Что я don' t понимают, то, что является RootViewController. I' ve приложение раскадровки с 3 сценами. Я хочу только, чтобы первая сцена была отображена в только в Режиме портрета. Добавление этого фрагмента кода в его class' файл.m didn' t изменяют что-либо. Что я должен сделать? – Isuru 08.11.2019, 05:22
find $directory -type f -name "*.in"

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

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

683
ответ дан 14.03.2020, 16:10
  • 1
    Интересный, createHTMLDocument обещание взглядов, если это weren' t для ограниченной поддержки. Синтаксические анализаторы HTML являются хорошими предложениями, хотя немного тяжелы, поскольку я предполагаю, что простой regex мог удалить src из изображения и продвинуть те данные на свойство элементов т.е. src2 так it' s все еще применимый. Я предполагаю, что надеялся на волшебное свойство, которое остановило это предварительно загружающее поведение, похож на более грязную фиксацию, необходим. Кроме того, иногда служа в другом формате isn' t возможный, т.е. для использования в сценарии Механика. – Gary Green 19.11.2019, 07:03
  • 2
    @flip: that' s различный вопрос. Отправьте новый вопрос, детализировав точно что you' d нравится делать и что you' ve попробовали до сих пор. – Mat 14.03.2020, 16:10
  • 3
    @Shnatsel: двойные кавычки действительно предотвращают расширение оболочки.Попробовать. – Mat 14.03.2020, 16:10
  • 4
    Это работает рекурсивно, также? – flip 14.03.2020, 16:11
  • 5
    да, find является рекурсивным по умолчанию. можно ограничить глубины, если Вы хотите (см. страницу справочника). – Mat 14.03.2020, 16:11
  • 6
    I' d нравится передавать все найденные файлы как аргументы файлу банки. Как это может быть выполнено? – flip 14.03.2020, 16:11
find {directory} -type f -name '*.extension'

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

find . -type f -name '*.csv'
159
ответ дан 14.03.2020, 16:10

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

find . -name 'pom.xml' -print
6
ответ дан 14.03.2020, 16:11
  • 1
    URW;) я don' t знают, что y яблоко изменило что-то вроде этого – Abo3atef 08.11.2019, 05:19

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

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

shopt -s extglob nullglob globstar

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

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

fileList=(**/*.csv)

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

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, эта опция будет неправильной.

4
ответ дан 14.03.2020, 16:11
  • 1
    Эй @B! Спасибо за человека ответа я думал, что это было легкой вещью, с которой все должны иметь дело, но похоже, что я поразил что-то более уклончивое, чем я все же. Ваш пример кода не работает на меня, но ссылка на другое сообщение очень полезна! – epologee 08.11.2019, 05:20

Теги

Похожие вопросы