
У меня есть каталог с именем 'dir', а в нем подкаталог с именем 'subdir'. В подкаталоге много файлов. Я хотел бы записать список этих файлов в файл CSV и сохранить его в каталоге 'dir' с помощью командной строки в Linux. Мой код создает файл CSV, но сохраняет его в subdir, а не в dir. Где я ошибаюсь? Я в каталоге dir;
dir$ ls subdir >names.csv
решение1
В качестве более простой альтернативы вы можете перейти в подкаталог и использовать
printf "%s\n" * >../list.csv
Это даст вам список, разделенный новой строкой и завершаемый новой строкой, без запятых. Вы можете увидеть его как дегенерированный файл csv с одним столбцом.
Если вы хотите включить скрытые файлы (файлы с именами, начинающимися с точки), вы можете использовать * .*
вместо единственного *
. Если вы хотите исключить имена каталогов . и .., используйте * .[^.]* ..?*
вместо этого . Всего:
printf "%s\n" * >../list.csv # For non-hidden files.
printf "%s\n" * .* >../list.csv # For all files.
printf "%s\n" * .[^.]* ..?* >../list.csv # For all files but `.` and `..`.
Но имейте в виду, что имена файлов в Linux могут содержать сами по себе символы новой строки. Фактически, единственным уникальным однобайтовым разделителем для имен файлов является нулевой байт.
Обновление в связи сэтот комментарий:
Предположим, что у вас есть несколько подкаталогов, нескрытое содержимое которых вы хотите каталогизировать в отдельных файлах в общем родительском каталоге. (Собрать все имена в одном файле гораздо короче, см.это элегантное решение. И, честно говоря, я не очень внимательно прочитал ваш комментарий.) Этого можно добиться в родительском каталоге (в вашем случае dir) с помощью
find . -mindepth 1 -maxdepth 1 -type d -exec bash -c 'cd {}; printf "%s\n" * >../$(basename {}).csv' \;
Для этого требуются программы find
, bash
, и basename
.
Используя его, следует проявлять особую осторожность, чтобы каталог не содержал файлы, имена которых конфликтуют с автоматически сгенерированными списками CSV.
Вот как это работает: find
рассматривает каждый файл, который находится ровно на один уровень ниже текущего каталога ( .
) — вот что -mindepth 1 -maxdepth 1
делает —: Если это каталог ( -type d
), он выполняет ( -exec
) команду между -exec
и завершающую \;
после замены пустых скобок ( {}
) именем этого каталога. Если мы обозначим это имя как <SUBDIR>
, это приведет к
bash -c 'cd <SUBDIR>; printf "%s\n" * >../$(basename <SUBDIR>).csv'
Это запускается bash
в подпроцессе, заставляя его выполнять аргумент опции -c
как скрипт оболочки, а именно:
cd <SUBDIR>;
printf "%s\n" * >../$(basename <SUBDIR>).csv
что почти то же самое, что и выше. Здесь выражение
$(basename <SUBDIR>)
расширяется до базового имени <SUBDIR>
. Это необходимо, поскольку <SUBDIR>
в вашем случае будет выполняться итерация по ./subdir1, ./subdir2 и т. д. Соответствующие базовые имена — subdir1, subdir2 и т. д.
решение2
Вы должны достичь этого, используядляпетля.
Если я правильно понимаю, вы хотите получить список файлов в подкаталоге. Так что сделайте что-то вроде этого:
$ cd dir
$ for files in subdir/*;do echo $files|cut -d '/' -f 2 >>filelist.csv;done
Теперь вы видите, что в вашем каталоге dir создан файл с именем «filelist.csv».