Как получить список файлов в каталоге в скрипте оболочки? - PullRequest
117 голосов
/ 13 марта 2010

Я пытаюсь получить содержимое каталога с помощью сценария оболочки.

Мой скрипт:

for entry in `ls $search_dir`; do
    echo $entry
done

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

Я знаю, что могу использовать for entry in *, но это будет работать только для моего текущего каталога.

Я знаю, что могу перейти в этот каталог, использовать for entry in *, а затем вернуться обратно, но моя конкретная ситуация не позволяет мне сделать это.

У меня есть два относительных пути $search_dir и $work_dir, и я должен работать над обоими одновременно, читая их, создавая / удаляя файлы в них и т. Д.

Так что мне теперь делать?

PS: я использую bash.

Ответы [ 9 ]

217 голосов
/ 13 марта 2010
for entry in "$search_dir"/*
do
  echo "$entry"
done
22 голосов
/ 23 октября 2014

Другие ответы здесь великолепны и отвечают на ваш вопрос, но это лучший результат Google для "bash get list of files in directory" (который я искал, чтобы сохранить список файлов), поэтому я подумал, что разместит ответ на эту проблему:

ls $search_path > filename.txt

Если вам нужен только определенный тип (например, любые файлы .txt):

ls $search_path | grep *.txt > filename.txt

Обратите внимание, что $ search_path является необязательным; ls> filename.txt создаст текущий каталог.

17 голосов
/ 13 марта 2010
for entry in "$search_dir"/* "$work_dir"/*
do
  if [ -f "$entry" ];then
    echo "$entry"
  fi
done
13 голосов
/ 27 апреля 2017

Это способ сделать это, когда синтаксис для меня проще понять:

yourfilenames=`ls ./*.txt`
for eachfile in $yourfilenames
do
   echo $eachfile
done

./ - текущий рабочий каталог, но его можно заменить любым путем
*.txt возвращает что-нибудь.txt
Вы можете легко проверить, что будет в списке, введя команду ls прямо в терминал.

По сути, вы создаете переменную yourfilenames, содержащую все, что команда list возвращает как отдельный элемент, а затем вы проходите через нее. Цикл создает временную переменную eachfile, которая содержит единственный элемент переменной, через которую она проходит, в данном случае имя файла. Это не обязательно лучше, чем другие ответы, но я нахожу это интуитивно понятным, потому что я уже знаком с командой ls и синтаксисом цикла for.

10 голосов
/ 04 апреля 2012
find "${search_dir}" "${work_dir}" -mindepth 1 -maxdepth 1 -type f -print0 | xargs -0 -I {} echo "{}"
1 голос
/ 23 апреля 2019
$ pwd; ls -l
/home/victoria/test
total 12
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  a
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  b
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  c
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:32 'c d'
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:31  d
drwxr-xr-x 2 victoria victoria 4096 Apr 23 11:32  dir_a
drwxr-xr-x 2 victoria victoria 4096 Apr 23 11:32  dir_b
-rw-r--r-- 1 victoria victoria    0 Apr 23 11:32 'e; f'

$ find . -type f
./c
./b
./a
./d
./c d
./e; f

$ find . -type f | sed 's/^\.\///g' | sort
a
b
c
c d
d
e; f

$ find . -type f | sed 's/^\.\///g' | sort > tmp

$ cat tmp
a
b
c
c d
d
e; f

Изменения

$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

Примечания:

  • .: текущая папка
  • удалить -maxdepth 1 для рекурсивного поиска
  • -type f: поиск файлов, а не каталогов (d)
  • -not -path '*/\.*': не возвращать .hidden_files
  • sed 's/^\.\///g': удалить добавленный ./ из списка результатов
0 голосов
/ 19 марта 2019

Принятый ответ не вернет префикс файлов с. Для этого используйте

for entry in "$search_dir"/* "$search_dir"/.[!.]* "$search_dir"/..?*
do
  echo "$entry"
done
0 голосов
/ 04 декабря 2018

Вот еще один способ перечисления файлов внутри каталога (с использованием другого инструмента, не столь эффективного, как некоторые другие ответы).

cd "search_dir"
for [ z in `echo *` ]; do
    echo "$z"
done

echo * Вывод всех файлов текущего каталога. Цикл for перебирает каждое имя файла и печатает на стандартный вывод.

Кроме того, если вы ищете каталоги внутри каталога, поместите его в цикл for:

if [ test -d $z ]; then
    echo "$z is a directory"
fi

test -d проверяет, является ли файл каталогом.

0 голосов
/ 19 февраля 2018

В версии для Linux, с которой я работаю (x86_64 GNU / Linux), работает:

for entry in "$search_dir"/*
do
  echo "$entry"
done
...