Простой сценарий командной строки

#shell

#оболочка

Вопрос:

Я пытаюсь написать простой сценарий оболочки. Скрипт переходит в папку, перебирает каждый файл, считывает каждую строку в каждом файле и печатает их.

Я делаю что-то не так?

 cd "My Directory Goes Here"

for myFile in `ls`
for line in `cat $myFile`;
    do   
    echo "$line"   
    done 
done
  

Ответ №1:

Вам не хватает do для внешнего цикла, и вам лучше использовать $() вместо обратных ссылок (легче читать, легче вкладывать, и это должно быть понятно любому современному человеку /bin/sh ). Кроме того, вам не нужно вызывать ls , чтобы получить список файлов в текущем каталоге, вы можете просто использовать * :

 # If you're trying to echo $myFile line by line and your lines
# may have embedded whitespace, then you'll want to change the
# input-field-separator to keep $(cat $myFile) for tokenizing
# the file on whitespace. If your files don't have whitespace
# in the lines, then you don't need to change IFS like this.
IFS=''

cd "My Directory Goes Here"
for myFile in *; do
    for line in $(cat $myFile); do
        echo $line
    done
done
  

В приведенном выше примере будут отсутствовать такие файлы, как .dotfile но вы можете использовать find , если они вам тоже нужны:

 for myFile in $(find . -type f -maxdepth 1); do
    # As above
  

И если вам приходится иметь дело с файлами, которые содержат пробелы в своих именах, то вам лучше использовать что-то другое, кроме оболочки, например Perl, Ruby или Python.

Комментарии:

1. Это выбранный ответ, но работает ли это? 1. Первый ответ не заботится о разделителе, он выплевывает содержимое слово за словом (через пробел), чем строка за строкой 2. команда find выдает ошибку, в которой говорится, что параметры должны предшествовать аргументам. 3. использование cat таким образом, как оно используется, является злоупотреблением cat. 🙂

2. @Lobo: 1. Зависит от формата файлов, хотя здесь есть некоторая двусмысленность, и настройка IFS='' исправит это, поэтому я добавлю обновление. 2. find Команда работает просто отлично, какого рода чрезмерно строгие ограничения и дисциплину find вы используете? 3. На самом деле это не жестокое обращение с кошками, это cat stuff | mangler скорее жестокое обращение с кошками, чем ненасильственное mangler < stuff , я слишком люблю кошек, чтобы оскорблять их 🙂

Ответ №2:

Используйте команду find и передайте результат в cat. Используйте xargs, чтобы избежать Argument list too long сбоя.

 find . -maxdepth 1 -type f -print0 | xargs -0 cat
  

Вы можете заменить весь ваш второй цикл for просто cat $myFile вместо того, чтобы брать каждую строку и печатать ее.

Обновить

 oldIFS='$IFS'
IFS='
'
for line in `find . -maxdepth 1 -type f -print0 | xargs -0 cat`; do
        echo $line
done
IFS='$oldIFS'
  

если вы хотите сделать это без изменения IFS (внутренний разделитель полей) —

 for file in `find . -maxdepth 1 -type f `; do
    while read line; do
        echo $line
    done<$file
done
  

Комментарии:

1. спасибо, но мне нужно использовать результат каждой прочитанной строки, возможно ли присвоить каждой строке текста переменную и как-то ее использовать?