#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. спасибо, но мне нужно использовать результат каждой прочитанной строки, возможно ли присвоить каждой строке текста переменную и как-то ее использовать?