Как мне перечислить одно имя файла на строку вывода в Linux?

229

Я использую ls -aкоманду, чтобы получить имена файлов в каталоге, но вывод в одной строке.

Как это:

.  ..  .bash_history  .ssh  updater_error_log.txt

Мне нужна встроенная альтернатива, чтобы получить имена файлов, каждое в новой строке, например:

.  
..  
.bash_history  
.ssh  
updater_error_log.txt
fixxxer
источник
3
ls предназначен для отображения списка для потребления человеком. Если вы используете ls для каких-либо других целей (например, чтобы получить список файлов в скрипте для повторения), вы наверняка используете неправильный инструмент.
Джулиано
2
@juliano - Это должно быть использовано сценарием Python. Почему вы называете это неправильным инструментом?
fixxxer
1
@fixxer В момент, когда вы передадите трубу lsна python, вы lsполучите по одному файлу на строку, как я объяснил в своем ответе.
Питер Г.
6
@fixxxer: Тогда вы действительно используете это неправильно. Форматирует листинг для вывода в пользовательском терминале. Он может заменять специальные символы в имени файла, он может пропускать символы, которые имеют особое значение и т. Д. ... Другими словами, ls форматирует список для пользователя. Вы хотите неформатированные имена файлов. Есть какая-то особая причина, по которой вы не используете модуль python 'glob'? docs.python.org/library/glob.html Есть также «fnmatch», «dircache» и другие.
Джулиано
@fixxer Вы действительно пытались lsвыводить pythonи наблюдать однострочный вывод в python?
Питер Г.

Ответы:

430

Используйте -1опцию (обратите внимание, что это «одна» цифра, а не строчная буква «L»), например:

ls -1a

Однако сначала убедитесь, что вы lsподдерживаете -1. GNU coreutils (устанавливается в стандартных системах Linux) и Solaris; но в случае сомнений используйте man lsили ls --helpили проверьте документацию. Например:

$ man ls
...
       -1     list one file per line.  Avoid '\n' with -q or -b
Берт F
источник
2
+1 Я не знал о -1 (-l да (ell не один)) Это видно на man-странице, но я все это время читал как ell :)
slashmais 7.10.10
@slashmais - Ах, хорошая мысль - легко ошибиться. Я уточнил в ответе.
Берт F
1
@dty: для GNU это задокументировано в ls --helpвыводе ... всегда устанавливается ;-)
Тони Делрой
3
Искал в Google linux ls one file per lineи это была лучшая статья. Не могу поверить, насколько многословен выбранный ответ или что у этого ответа меньше голосов, чем у того, который доносит до кошки. ls -1FTW.
кранток
3
lsпо умолчанию -1поведение, когда выход не подключен к терминалу.
codeforester
132

Да, вы можете легко сделать lsвывод одно имя файла в строке:

ls -a | cat

Объяснение: Команда lsопределяет, выводится ли вывод на терминал, в файл или канал и корректируется соответствующим образом.

Так что, если вы переходите ls -aна Python, он должен работать без особых мер.

Петр Григорьевич
источник
2
Вау, это великолепно. Преимущество перед принятым ответом - этот на самом деле работает на оболочке Android / adb - где lsтолько урезанная версия, поэтому не поддерживает-1
mkilmanas
Как бы вы избежать .и ..«файлы» , показывая на выходе , хотя?
matanster,
@matanster: Это зависит от того, хотите ли вы вообще увидеть дот-файлы? Если нет, просто опустите опцию -a.
Питер Г.
29

Ls предназначен для потребления человеком, и вы не должны анализировать его вывод .

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

В python нет абсолютно никаких причин для вызова ls. Python имеет все lsвстроенные функции. Используется os.listdirдля просмотра содержимого каталога и os.statили osдля получения метаданных файла. Другие функции в osмодулях также могут иметь отношение к вашей проблеме.


Если вы обращаетесь к удаленным файлам через ssh, достаточно надежный способ перечисления имен файлов - через sftp:

echo ls -1 | sftp remote-site:dir

Это печатает одно имя файла в строке и, в отличие от lsутилиты, sftpне печатает непечатаемые символы. Вы по-прежнему не сможете надежно перечислить каталоги, в которых имя файла содержит новую строку, но это делается редко (помните, что это потенциальная проблема безопасности, а не проблема удобства использования).

В python (знайте, что метасимволы оболочки должны быть экранированы remote_dir):

command_line = "echo ls -1 | sftp " + remote_site + ":" + remote_dir
remote_files = os.popen(command_line).read().split("\n")

Для более сложных взаимодействий посмотрите пакетный режим sftp в документации.

В некоторых системах (Linux, Mac OS X, возможно, в некоторых других приложениях, но определенно не в Windows) другой подход заключается в монтировании удаленной файловой системы через ssh с помощью sshfs , а затем в локальном режиме.

Жиль "ТАК - перестань быть злым"
источник
Я подключен через SSH к удаленной машине. Я не нашел способа выполнить функцию Python, такую ​​как os.listdir, на удаленной машине в одну строку. Отсюда и этот вопрос. Я не хочу писать скрипт для простого перечисления файлов. Есть ли другой способ обойти эту проблему?
fixxxer 11.10.10
@fixxxer: ssh меняет ситуацию, это то, что вы должны были упомянуть в своем первоначальном вопросе! Я думаю, что sftp подходит для вашего случая использования.
Жиль "ТАК - перестань быть злым"
Я прошу прощения за путаницу. Есть ли способ, как я могу вставить пароль в "command_line", а?
fixxxer
@fixxxer: я не знаю, авторы ssh не одобряют пароли, хранящиеся в простом тексте, и не стремятся сделать это легко. Вы должны действительно настроить аутентификацию на основе ключей (в Интернете есть множество обучающих программ и вопросов на superuser.com ).
Жиль "ТАК - перестань быть злым"
11

ты можешь использовать ls -1

ls -l также сделаю работу

ILF
источник
В верхнем ответе уже упоминается то, что вы сказали. также вопрос конкретно говорит, ls -lчто не следует использовать.
DevX
2

Легко, если ваши имена файлов не содержат символов новой строки:

find . -maxdepth 1

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

find . -maxdepth 1 -print0

Печать этого на терминале, вероятно, будет отображаться в виде одной строки, потому что нулевые байты обычно не печатаются. Некоторым программам может потребоваться особая опция для обработки ввода с нулевым разделением, например sort, s -z. Ваш собственный сценарий также должен был бы учитывать это.

8bittree
источник