Работа с файлами в каталоге при помощи циклов
Не все утилиты командной строки позволяют запускать одну команду для нескольких файлов одновременно, но с помощью сценариев оболочки и цикла for вы можете автоматически повторить любую команду.
Цикл – один из самых мощных аспектов в программировании. Он позволяет вам многократно применять одну и ту же логику к группе элементов, требуя при этом минимального количества кода.
В этом мануале мы научим вас перебирать файлы и применять команды с помощью оболочки Bash или zsh.
1: Перебор файлов
В этом мануале мы будем использовать цикл сценариев для оболочки. Этот конкретный метод управления встроен в оболочку командной строки Bash или zsh.
Вы можете применить следующие команды к любому каталогу по вашему выбору, но в этом мануале мы будем использовать тестовый каталог. Создайте каталог и несколько файлов, на которых можно потренироваться.
Сначала создайте каталог:
mkdir looping
Затем перейдите в него:
cd looping
С помощью команды touch создайте несколько текстовых файлов:
touch file-1.txt
touch file-2.txt
touch file-3.txt
touch file-4.txt
touch file-5.txt
Вы также можете быстро создать эти файлы, задав диапазон в скобках:
touch file-{1..5}.txt
Чтобы просмотреть каталог и затем вывести имя файла, выполните следующую команду:
for FILE in *; do echo $FILE; done
Вы увидите следующий результат:
file-1.txt
file-2.txt
file-3.txt
file-4.txt
file-5.txt
Вы, наверное, заметили, что здесь используется подстановочный знак *. Он позволяет циклу for захватить каждый файл в каталоге. Вы можете изменить подстановочный знак на file-*, чтобы вывести все файлы, имена которых начинаются с file-, или на *.txt, чтобы вывести только текстовые файлы.
Теперь, когда вы знаете, как перебирать файлы в каталоге, давайте применим команду к этим файлам.
2: Применение команды
Все файлы, которые вы создали в предыдущем разделе, были созданы с помощью команды touch. Эти файлы пусты, поэтому применять к ним команду cat было бы не очень полезно.
К счастью, вы можете вставить текст в каждый файл с помощью одной команды, используя аналогичный цикл for.
Выполните следующую команду, чтобы вставить имя файла, новую строку и текст «Loops Rule!» в каждый файл:
for FILE in *; do echo -e "$FILE\nLoops Rule\!" > $FILE; done
Флаг -e в команде echo гарантирует сохранение новых строк.
Восклицательный знак нужно избежать с помощью обратного слеша, чтобы оболочка не интерпретировала символ как команду оболочки.
Теперь переберите каждый файл и выведите его содержимое:
for FILE in *; do cat $FILE; done
Теперь каждый файл содержит имя файла в первой строке и сообщение о том, что циклы классные, во второй строке.
file-1.txt
Loops Rule!
file-2.txt
Loops Rule!
file-3.txt
Loops Rule!
file-4.txt
Loops Rule!
file-5.txt
Loops Rule!
Дальше мы попробуем объединить эти примеры: сначала записать данные в файл, а затем отобразить его содержимое в одном цикле:
for FILE in *; do echo -e "$FILE\nLoops Rule\!" > $FILE; cat $FILE; done
Вы увидите следующий результат:
file-1.txt
Loops Rule!
file-2.txt
Loops Rule!
file-3.txt
Loops Rule!
file-4.txt
Loops Rule!
file-5.txt
Loops Rule!
При помощи точки с запятой (;) вы можете связать вместе любые необходимые команды.
Теперь давайте рассмотрим практический пример: создание резервных копий файлов.
3: Создание резервных копий файлов
Теперь, когда вы знаете, как работает цикл for, давайте попробуем сделать что-то полезное: возьмем каталог файлов и сделаем резервные копии с расширением .bak.
Выполните в своей оболочке следующую команду, которая создает резервную копию для каждого файла:
for FILE in *; do cp $FILE "$FILE.bak"; done;
С помощью команды ls отобразите все файлы:
ls -l
Вы увидите такой результат:
total 40K
-rw-r--r-- 1 8host 8host 29 Nov 7 18:34 file-1.txt
-rw-r--r-- 1 8host 8host 29 Nov 7 18:41 file-1.txt.bak
-rw-r--r-- 1 8host 8host 29 Nov 7 18:34 file-2.txt
-rw-r--r-- 1 8host 8host 29 Nov 7 18:41 file-2.txt.bak
-rw-r--r-- 1 8host 8host 29 Nov 7 18:34 file-3.txt
-rw-r--r-- 1 8host 8host 29 Nov 7 18:41 file-3.txt.bak
-rw-r--r-- 1 8host 8host 29 Nov 7 18:34 file-4.txt
-rw-r--r-- 1 8host 8host 29 Nov 7 18:41 file-4.txt.bak
-rw-r--r-- 1 8host 8host 29 Nov 7 18:34 file-5.txt
-rw-r--r-- 1 8host 8host 29 Nov 7 18:41 file-5.txt.bak
Теперь у вас есть резервные копии всех ваших файлов. Их расширение указывает, что это резервные копии.
Создание копий в одном каталоге – это далеко не единственная задача, которую вы можете выполнить с помощью цикла. Вы можете также указать новый путь для файлов резервных копий. Следующая команда сохраняет резервные копии в папке /tmp/my-backups (если указанный каталог уже существует):
for FILE in *; do cp $FILE "/tmp/my-backups/$FILE.bak"; done;
Резервные копии будут созданы в новом каталоге.
Заключение
В этом мануале мы поэкспериментировали с циклом for и научились использовать его для перебора файлов и применения команд к нескольким фалам в каталоге.