Как вывести только имена файлов (с пробелами) в ls -Al?


81

Я должен отображать только имена файлов или каталогов с этой конструкцией:

ls -Al | while read string
do
...
done

ls -Al выход :

drwxr-xr-x  12 s162103  studs         12 march 28 12:49 personal domain
drwxr-xr-x   2 s162103  studs          3 march 28 22:32 public_html
drwxr-xr-x   7 s162103  studs          8 march 28 13:59 WebApplication1

Например, если я попробую:

ls -Al | while read string
do
echo "$string" | awk '{print $9}
done

затем выводить только файлы и каталоги без пробелов. Если в файле или каталоге есть пробелы типа «персональный домен», это будет только слово «персональный».

Мне нужно очень простое решение. Может быть, есть лучшее решение, чем awk.


2
Почему не просто ls -Al *' '*? lsВывод разбора никогда не приводит ни к чему хорошему.
manatwork

1
Если вам нужно что-то, что будет работать в любом * nix, попробуйте не использовать ls -Al | while. Простой и более надежный способ for string in *; do echo "$string"; done.
forcefsck

нужно только с этой конструкцией .. ладно, не просто, любое решение!
Алекс Зерн

1
Зачем вам нужно ls ? Разбор lsи "работа во всех * nix и не сломается, если что-то случилось" не идут хорошо вместе.
Terdon

Ответы:


100

Вы действительно не должны анализировать выводls . Если это домашнее задание, и вы обязаны это сделать, ваш профессор не знает, о чем они говорят. Почему бы вам не сделать что-то вроде этого:

Добро...

find ./  -printf "%f\n"

или же

for n in *; do printf '%s\n' "$n"; done

...плохо...

Если вы действительно хотите использовать его ls, вы можете сделать его более надежным, выполнив что-то вроде этого:

ls -lA | awk -F':[0-9]* ' '/:/{print $2}'

... и безобразный

Если вы настаиваете на том, что делаете это неправильно, опасно и вам просто нужно использовать whileцикл, сделайте следующее:

ls -Al | while IFS= read -r string; do echo "$string" | 
    awk -F':[0-9]* ' '/:/{print $2}'; done

Если серьезно, просто не надо.


drwx------ 2 s162103 studs 3 oct. 9 2012 .ssh drwxr-xr-x 3 s162103 studs 6 oct. 25 09:02 .subversion drwxrwxrwt 3 s162103 studs 3 nov. 15 2012 .TempoItemsиногда у меня свидание без времени, только год и пустышка возвращаются пустыми
Алекс Зерн

1
@AlexZern Ну, это одна из причин, по которой вы не анализируете вывод ls.
Terdon

2
@AlexZern зачем тебе вообще нужен -lпереключатель? Если вам нужны только имена файлов, просто запустите ls -A. Использование -lпросто усложняет вашу жизнь, так как теперь вам нужно анализировать результаты.
Terdon

потому что мне нужна дополнительная информация, такая как доступ, дата, владелец и т. д. И я написал огромный скрипт, который хорошо работает, за исключением печати файлов и директорий с пробелами.
Алекс Зерн

3
Хорошо, тогда. У нас есть проблема XY . lsэто просто не лучший способ получить то, что вам нужно. Почему бы вам не опубликовать новый вопрос, объясняющий информацию, которую вы хотите собрать, и мы можем предложить способы сделать это. Кроме того, вы можете использовать свой сценарий как есть и использовать одно из предложенных выше предложений только для печати названия. А если серьезно, не разбирайся ls, просто скажи нам точно, что ты пытаешься сделать в новом вопросе.
Terdon

74

Есть ли какая-то причина, по которой ls -A1* не будет работать?

Например:

$ touch file1 file2 file\ with\ spaces
$ ls -Al
total 0
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file1
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file2
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file with spaces
$ ls -A1
file1
file2
file with spaces
$

* Примечание: это заглавная буква А и номер один.


4
-1 гений. Я не знал, что было доступно. (Я знаю, я знаю. RTFM)
Ленивый кодер

это работает только для текущего каталога, если вы хотите перечислить имена файлов из другого каталога, скажем, ~ / projects, тогда вы получите полные пути вместо имен файлов
thecotne

@thecotne на Mac 10.9.5 просто перечисляет имена файлов. Какую ОС вы используете?
AJP

я запускаю этот ls ~ / projects / *. sublime-project -A1 для ls ~ / projects -A1 я получаю только имена
thecotne

3
@TheLazyCoder не должен был читать руководство.
c24w

41

Интересно, почему никто не упомянул эту простую команду:

ls -a | sort

2
Brilliant! Любая идея, как конвейер sortприводит к тому, что блок из нескольких столбцов не разворачивается в один столбец?
msciwoj

@msciwoj он просто берет любые строки, разделенные пробелами, и печатает их, отсортированные по конечным линиям
Бен

ИДЕАЛЬНЫЙ! Почему этот не помечен как реальный ответ?
劇場 期 劇場

3
Это работает здесь, потому что lsвозвращается к ls -1(вывод одного столбца), когда его вывод не идет в терминал (и отключает цитирование / замену непечатных символов; @Kusalananda, вы lsне POSIX-совместимы, если это все еще происходит). lsвывод уже отсортирован. Так что передача его sortв лучшем случае ничего не будет делать, а в худшем случае искажает вывод (если имена файлов содержат символы новой строки) или завершится неудачно для имен файлов, которые не являются текстовыми. ls -a | catбыло бы лучше. Или даже лучше, ls -A1как уже упоминалось (и потому, что вы обычно хотите замены / цитирования при отображении на терминале)
Стефан Шазелас

1
@ StéphaneChazelas отметил. lsведет себя по-разному, когда вывод не является терминалом.
Кусалананда

3

Вы не можете анализировать выходные данные ls, не говоря уже о том, ls -lчто символ новой строки, как и пробел, является таким же допустимым символом, как и любой другой символ в имени файла. Кроме того, вам нужно рассмотреть символические ссылки, которые имеют вывод, как ... foo -> bar.

Зачем вам в -lлюбом случае использовать, если вы хотите только имя файла?

Просто сделать:

for file in *; do
  ...
done

Если вы хотите включить точечные файлы (кроме .и ..), в зависимости от оболочки:

zsh:

for file in *(ND); do
  ...
done

bash:

shopt -s nullglob dotglob
for file in *; do
  ...
done

ksh93:

FIGNORE='@(.|..)'
for file in ~(N)*; do
  ...
done

POSIXly:

for file in .[!.]* ..?* *; do
  [ -e "$file" ] || [ -L "$file" ] || continue
  ...
done


1
ls -Al | tr -s ' ' | cut -f9- -d' '

сжать несколько пробелов в единичные пробелы с помощью tr, тогда вы можете использовать cut для разделения полей


1

Попробуйте ( bash, zsh, ksh93синтаксис):

find . -type f -print0 | while IFS= read -r -d '' filename; do
  ...
done

Это становится рекурсивным и выводится только в обычных файлах (то есть без директорий или символических ссылок / fifos / devices ...).

Смотрите также:



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.