как перечислить файлы из определенных каталогов

У меня есть список каталогов в текстовом файле, каждый может рассказать мне, как перечислять файлы только внутри каталогов, которые находятся в текстовом файле

-1
задан 12 February 2018 в 09:34

8 ответов

Я точно не знаю сценарий, но объединение одного из них внутри цикла for в скрипте будет делать то, что вы хотите сделать.

Чтобы перечислить files only inside a directory, вы можете сделать один из них

Используя ls

$ ls -p | grep -v / OR $ ls -al | grep '^-'

Используя find

$ find . -maxdepth 1 -type f
-1
ответ дан 17 July 2018 в 21:00

Вы можете использовать [F4] и [F5] Command Substitution для этого:

find $(</path/to/path_file) -type f

Это просто перечисляет все f ile, содержащиеся в каждом каталоге, упомянутом в /path/to/path_file. Конечно, вы можете настроить выход find дальше, например. добавив параметр -ls.

Пример run

$ tree . ├── path_file ├── test1 │   ├── 1 │   └── 2 └── test2 ├── 3 └── 4 $ cat path_file /path/to/test1 /path/to/test2 $ find $(</path/to/path_file) -type f /path/to/test1/2 /path/to/test1/1 /path/to/test2/4 /path/to/test2/3

Здесь я использую абсолютные пути, поэтому не имеет значения, в какой директории find вызывается. Если path_file содержит относительные пути, вам нужно вызвать его в правильном каталоге - представьте, что каждый /path/to заменен на . в приведенном выше примере.

Если ваши пути содержат пробелы, вы можете установить bash Замена команды в новую строку с IFS=$'\n' перед вызовом find, таким образом, только линия новой линии будет рассматриваться как граница между путями.

Если вы хотите перейти по каждой строке, я настоятельно рекомендую parallel, чтобы остаться с find:

parallel find {} -type f :::: /path/to/path_file

parallel обрабатывает пробелы в аргументах правильно по дизайну.

3
ответ дан 17 July 2018 в 21:00

Здесь есть две проблемы: один очень простой - перечисление файлов в каталогах, а другое, что может быть немного более неприятным - чтение файла по строкам и передача строк из этого файла в качестве аргументов.

Классический способ сделать это через петлю while IFS= read -r, и мы можем добавить к нему другие вещи

while IFS= read -r line || [ -n "$line" ] ; do [ "x$line" = "x" ] && continue [ -d "./$line" ] && ls "./$line" done < ./dirs.txt

Происходит несколько вещей:

IFS= read -r line часть будет читать строку без выполнения разбиения слов; это означает, что если у вас есть <space><space>directory_name, он будет читаться точно так же, как только directory_name. ./ рядом с проверками того, существует ли указанная директория в первую очередь, и ls - это защита от имен файлов, которые могут начинаться с -. Имена файлов, такие как -directory, могут быть неверно истолкованы командами как флаг -d с соответствующим значением irectory для этого флага; конечно, это приведет к ошибке, если такой флаг не существует для команды. [ "x$line" = "x" ] && continue будет проверять пустую переменную / пустую строку. Если переменная пуста, ls выводит содержимое для ./, что является неправильным поведением.

Рекурсивный случай того же самого события может быть либо через find, либо в виде десертов, либо через globstar:

shopt -s globstar while IFS= read -r line || [ -n "$line" ] ; do [ "x$line" = "x" ] && continue [ -d "$line" ] && for i in "$line"/** ; do ls "$i" done done < "/path/to/dirs.txt"
2
ответ дан 17 July 2018 в 21:00

Это простой пример, чтобы сделать это из командной строки:

ls `cat ./dirs.txt`

Заменить «dirs.txt» с именем файла, содержащего список ваших каталогов. Файл dirs.txt должен находиться в текущем рабочем каталоге, если вы не указали путь к dirs.txt. Чтобы перечислить файлы по одному экрану за раз:

ls `cat ./dirs.txt` | more

Это будет более сложно. Как Сергей Колодяжный отметил в комментариях, это будет работать неправильно, если ваш dirs.txt содержит каталог, в котором есть пробел или вкладки.

0
ответ дан 17 July 2018 в 21:00

Я точно не знаю сценарий, но объединение одного из них внутри цикла for в скрипте будет делать то, что вы хотите сделать.

Чтобы перечислить files only inside a directory, вы можете сделать один из них

Используя ls

$ ls -p | grep -v / OR $ ls -al | grep '^-'

Используя find

$ find . -maxdepth 1 -type f
-1
ответ дан 23 July 2018 в 21:41

Вы можете использовать [F4] и [F5] Command Substitution для этого:

find $(</path/to/path_file) -type f

Это просто перечисляет все f ile, содержащиеся в каждом каталоге, упомянутом в /path/to/path_file. Конечно, вы можете настроить выход find дальше, например. добавив параметр -ls.

Пример run

$ tree . ├── path_file ├── test1 │   ├── 1 │   └── 2 └── test2 ├── 3 └── 4 $ cat path_file /path/to/test1 /path/to/test2 $ find $(</path/to/path_file) -type f /path/to/test1/2 /path/to/test1/1 /path/to/test2/4 /path/to/test2/3

Здесь я использую абсолютные пути, поэтому не имеет значения, в какой директории find вызывается. Если path_file содержит относительные пути, вам нужно вызвать его в правильном каталоге - представьте, что каждый /path/to заменен на . в приведенном выше примере.

Если ваши пути содержат пробелы, вы можете установить bash Замена команды в новую строку с IFS=$'\n' перед вызовом find, таким образом, только линия новой линии будет рассматриваться как граница между путями.

Если вы хотите перейти по каждой строке, я настоятельно рекомендую parallel, чтобы остаться с find:

parallel find {} -type f :::: /path/to/path_file

parallel обрабатывает пробелы в аргументах правильно по дизайну.

3
ответ дан 23 July 2018 в 21:41
  • 1
    Вот как вы учите их плавать ..... просто бросайте их в воду! лол – stumblebee 12 February 2018 в 11:24
  • 2
    @stumblebee Что не так и так сложно в замене команд? Фактически, ваш ответ использует его также, как раз с более медленной альтернативой cat. ;) – dessert 12 February 2018 в 11:29

Здесь есть две проблемы: один очень простой - перечисление файлов в каталогах, а другое, что может быть немного более неприятным - чтение файла по строкам и передача строк из этого файла в качестве аргументов.

Классический способ сделать это через петлю while IFS= read -r, и мы можем добавить к нему другие вещи

while IFS= read -r line || [ -n "$line" ] ; do [ "x$line" = "x" ] && continue [ -d "./$line" ] && ls "./$line" done < ./dirs.txt

Происходит несколько вещей:

IFS= read -r line часть будет читать строку без выполнения разбиения слов; это означает, что если у вас есть <space><space>directory_name, он будет читаться точно так же, как только directory_name. ./ рядом с проверками того, существует ли указанная директория в первую очередь, и ls - это защита от имен файлов, которые могут начинаться с -. Имена файлов, такие как -directory, могут быть неверно истолкованы командами как флаг -d с соответствующим значением irectory для этого флага; конечно, это приведет к ошибке, если такой флаг не существует для команды. [ "x$line" = "x" ] && continue будет проверять пустую переменную / пустую строку. Если переменная пуста, ls выводит содержимое для ./, что является неправильным поведением.

Рекурсивный случай того же самого события может быть либо через find, либо в виде десертов, либо через globstar:

shopt -s globstar while IFS= read -r line || [ -n "$line" ] ; do [ "x$line" = "x" ] && continue [ -d "$line" ] && for i in "$line"/** ; do ls "$i" done done < "/path/to/dirs.txt"
2
ответ дан 23 July 2018 в 21:41

Это простой пример, чтобы сделать это из командной строки:

ls `cat ./dirs.txt`

Заменить «dirs.txt» с именем файла, содержащего список ваших каталогов. Файл dirs.txt должен находиться в текущем рабочем каталоге, если вы не указали путь к dirs.txt. Чтобы перечислить файлы по одному экрану за раз:

ls `cat ./dirs.txt` | more

Это будет более сложно. Как Сергей Колодяжный отметил в комментариях, это будет работать неправильно, если ваш dirs.txt содержит каталог, в котором есть пробел или вкладки.

0
ответ дан 23 July 2018 в 21:41
  • 1
    Это выведет ошибку для строк в текстовом файле с пробелами в них или вкладками. Я предлагаю вам использовать xargs с опцией --arg-file для чтения в файле, а затем передать его на ls. Также читайте mywiki.wooledge.org/DontReadLinesWithFor – Sergiy Kolodyazhnyy 12 February 2018 в 11:42
  • 2
    @dessert никогда не использовал параллель самостоятельно, поэтому не могу комментировать это :) Что же с ::::? – Sergiy Kolodyazhnyy 12 February 2018 в 11:55
  • 3
    @SergiyKolodyazhnyy Это может стать еще более сложным, если в каталоге есть пробелы. – stumblebee 12 February 2018 в 12:02
  • 4
    @dessert Я никогда не использовал параллель. Это хорошая информация. – stumblebee 12 February 2018 в 12:20
  • 5
    @dessert Да, это. И я также добавил бы --no-run-if-empty к флагам xargs только ради полноты – Sergiy Kolodyazhnyy 12 February 2018 в 12:39

Другие вопросы по тегам:

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