список в оболочке скрипта bash

я сделал этот скрипт

#!/bin/bash

liste=`ls -l`
for i in $liste
do
    echo $i
done

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

У меня есть :

my_name
etud 
4096
Oct
8
10:13

и я хочу иметь:

my_name etud 4096 Oct 8 10:13

Конечная цель скрипта — проанализировать каждую строку; это причина, по которой я хочу иметь возможность восстановить всю строку. Возможно, список не лучшее решение, но я не знаю, как восстановить строки.


person federem    schedule 10.10.2013    source источник
comment
возможный дубликат Как вы обрабатываете вывод команды в оболочке построчно?   -  person Mark Reed    schedule 10.10.2013
comment
@federem Почему бы вам не сообщить нам, какую конкретную информацию вы хотите получить от линии? Отметка времени? Размер? Есть лучшие способы получить эти вещи, не связанные с ls.   -  person Charles Duffy    schedule 11.10.2013


Ответы (5)


Для начала предположим, что ни одно из ваших имен файлов никогда не содержит символов новой строки:

ls -l | IFS= while read -r line; do
    echo "$line"
    # Do whatever else you want with $line
done

Если ваши имена файлов могут содержать новые строки, все становится сложнее. В этом случае лучше (хотя и медленнее) использовать stat для извлечения нужных метаданных из каждого файла по отдельности. Обратитесь к man stat за подробностями о том, как работает ваш местный вариант stat, поскольку он, к сожалению, не очень стандартизирован.

for f in *; do
    line=$(stat -c "%U %n %s %y" "$f")  # One possibility
    # Work with $line as if it came from ls -l
done
person chepner    schedule 10.10.2013
comment
Истинный. Однако, если вам все равно нужно запускать новый процесс для каждого файла, контроль над выводом, который позволяет stat, может быть более удобным. (Но да, я просто упустил из виду, что вы можете вызывать ls для каждого файла.) - person chepner; 11.10.2013

Вы можете заменить

echo $i

с

echo -n "$i "

echo -n выводит на консоль без новой строки.

person Fabrice Jammes    schedule 10.10.2013
comment
echo -n не является стандартом POSIX. printf — это безопасный портативный подход. - person Charles Duffy; 10.10.2013
comment
@ Чарльз Даффи, это определено в IEEE Std 1003.1-2001 POSIX. - person Jim Black; 10.10.2013
comment
@JimBlack Только как расширение XSI. - person Charles Duffy; 11.10.2013
comment
Цитата @JimBlack: эхо System V не поддерживает никаких параметров, но допускает escape-последовательности в своих операндах, как описано для реализаций XSI в разделе ОПЕРАНДЫ. Еще одна цитата: невозможно использовать эхо во всех системах POSIX, если не опущены как -n (в качестве первого аргумента), так и escape-последовательности. - person Charles Duffy; 11.10.2013

Другой способ сделать это с циклом while и без канала:

#!/bin/bash

while read line
do
    echo "line: $line"
done < <(ls -l)
person Labynocle    schedule 10.10.2013
comment
Это правильно (за исключением использования read без -r — таким образом интерпретируются escape-последовательности — и оставляются $IFS по умолчанию — и, таким образом, удаляются конечные пробелы), если целью является демонстрация чтения из потока. Неправильно, если целью является демонстрация чтения списка файлов (некоторые люди действительно думают, что ls - правильный способ сделать это!). Было бы хорошо, если бы ответ был более четким. - person Charles Duffy; 10.10.2013

Во-первых, я надеюсь, что вы не используете ls в своем реальном коде, а только в качестве примера. Если вам нужен список файлов, ls не подходит; подробности см. на http://mywiki.wooledge.org/ParsingLs.

Во-вторых, современные версии bash имеют встроенную функцию readarray.

Попробуй это:

readarray -t my_array < <(ls -l)
for entry in "${my_array[@]}"; do
  read -a pieces <<<"$entry"
  printf '<%s> ' "${pieces[@]}"; echo
done

Во-первых, он создает массив (называемый my_array) со всеми выводами выполняемой команды.

Затем для каждой строки в этом выводе он создает массив с именем pieces и выделяет каждую часть со скобками со стрелками вокруг них.

Если вы хотите читать построчно, а не весь файл сразу, см. http://mywiki.wooledge.org/BashFAQ/001 ("Как я могу прочитать файл (поток данных, переменную) построчно (и/или по полю)?")

person Charles Duffy    schedule 10.10.2013
comment
<(ls -l) потерпит неудачу при тех же обстоятельствах, что и ls -l | while read.... - person chepner; 10.10.2013
comment
@chepner Если вы имеете в виду ls, я не думаю, что когда-либо подразумевал что-то обратное - см. Первый абзац моего ответа. (Тем не менее, если вы не рассматриваете возможность потери какого-либо локального состояния процесса, связанного с прочитанным вами содержимым, с ошибкой, я не могу согласиться с точностью возражения в общем случае, не связанном с ls) - person Charles Duffy; 11.10.2013

Присоединение к предыдущим ответам с необходимостью хранить список файлов в переменной. Ты можешь это сделать

echo -n "$list"|while read -r lin
do
 echo $lin
done
person FeLocci    schedule 10.10.2013