Как рекурсивно прочитать папку и ее подпапки и выполнить поиск файла

#linux #bash #shell

Вопрос:

Я новичок в написании сценариев оболочки, поэтому сделаю все возможное, чтобы обобщить все.

Я пишу сценарий с целью зайти в каталог и найти файл (readme.txt) в каждой вложенной папке и следуйте инструкциям, указанным в файле (readme.txt).

Код, который я написал до сих пор:

 #! /bin/bash  # Creating directory that the files are going to be moved into  if ! (mkdir /dir1/dir2/backupdirgt; /dev/null); then  echo "Directory already exists. "  else  echo "Directory successfully created. "  fi  # Moving old files to backup directory  cd /dir1/dir2/maindir-* find /dir1 -mindepth 1 -type f -name "readme.txt" | while read z  do  if grep -i move "$z" gt; /dev/null; then   mv /xdir0/$z /dir1/dir2/backupdir  # /xdir0/ is the parent directory of /xdir1/  # readme.txt file does not include /xdir0/ so I added it when moving the files    fi   done  

Выход по току: /dir1/dir2/maindir/subfolder1/readme.txt

В «maindir» есть несколько вложенных папок.

основной каталог/подпапка1 основной каталог/подпапка2 основной каталог/подпапка3

В каждой вложенной папке есть readme.txt файл. Содержание readme.txt выглядело бы примерно так:

 Date: 2021-08-12 Applicable Version: xx.x Description: Quick summary of files  Steps to apply:  1. move the following files into a backup location  * xdir1/xdir2/xdir3/xdir4/filename-*.jar  * xdir1/xdir2/xdir3/xdir4/filename1-*.jar  2. done. work completed.  

Сценарий будет анализировать каждую строку после того, как будет распознано «перемещение», и остановится на «Сделано». Строка «Работа завершена», поскольку все файлы были перемещены в созданный мной каталог резервной копии.

Любая помощь будет очень признательна.

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

1. Я что точное содержание readme.txt ? Если нет, отредактируйте свой вопрос и укажите точное содержание.

2. Привет, Дэвид, «Дата», «Применимая версия» и «Описание» были добавлены из readme.txt файл. Это точное содержание. К вашему сведению — Между «Датой», «Применимой версией» и «Описанием» в readme.txt файл. Это не позволило бы удалить пробелы между ними, когда я редактировал сообщение.

3. Я отформатировал текстовый файл для вас. Дважды проверьте, что теперь он отражает правильное readme.txt содержимое. (включая интервал и то , действительно ли строки, в которых есть файлы для перемещения, начинаются с a * , и что строки 1. move и действительно начинаются с 2. Done ... 1. и 2. , и может ли быть более одного набора 1. переместить` и 2. Done ... строки.)

4. Спасибо тебе, Дэвид. Я убрал пробелы и сменил «Готово. Работа завершена.» до «сделано. работа завершена». Да, строки, в которых есть файлы для перемещения, начинаются с * и 1. переместить и 2. готово, начинаются с 1. и 2. Я полагаю, что можно было бы добавить еще несколько строк, но пока я хотел оставить все как есть и добавить к нему позже.

Ответ №1:

Вы можете использовать mkdir -p newfolder , который создаст его, или молча продолжить, если папка уже существует. Таким образом, вам не придется проверять, существует ли папка.

Вам не нужна sleep 1

На самом деле вы можете сначала использовать find -mindepth 1 -type f -name "readme.txt" , чтобы найти папки, в которых у вас есть файл readme:

 find /dir1 -mindepth 1 -type f -name "readme.txt"|while read z do  if grep -i move "$z" gt; /dev/null;then  ... do your mv magic  fi done  

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

1. Я обновил свой исходный код, чтобы отразить внесенные изменения. Однако при запуске сценария я получаю следующую ошибку — строка 77: синтаксическая ошибка: неожиданный конец файла

2. нужно ли нам угадывать, как выглядит весь ваш сценарий? 🙂 Эта ошибка предполагает, что некоторые из if них неправильно закрыты или петли не закрыты.. Поделитесь всем своим сценарием или попробуйте выполнить локальную отладку в том месте, где возникла ваша проблема

3. Вот и весь сценарий, который я запускаю. Исправлена ошибка «неожиданный конец файла», и теперь код работает нормально (удален для цикла). Однако он не считывает путь к файлам .jar, указанным внутри readme.txt файл и переместите их в созданный мной каталог резервной копии. Вместо этого он перемещает readme.txt сам файл помещается в папку /dir1/dir2/maindir.

4. Похоже, что переменная $z-это pwd или путь к каталогу readme.txt файл. Как я могу вместо этого указать путь к каталогу для файла .jar?

Ответ №2:

Лучший способ-использовать трубу, вы начинаете звонить find :

 # find all 'readme.txt' files from "$DIR" and subdirectories and make a loop # for each one. your_backup_location=/home/user/blah/blah/foo/bar  find "$DIR" -name 'readme.txt' -print | while read file do  # Assuming this is executed in subdirectory  # xdir1/xdir2/xdir3/xdir4, where readme.txt was found...  # $file contains the readme.txt full path from starting dir.  echo "executing commands from $file" gt;amp;2 # print it on stderr  ( # this will start a subshell, so we can work in the directory where readme.txt is.  cd "$(dirname "$file")" # move to dir where readme.txt is located.  . readme.txt # read commands from readme.txt file. Protect comment lines with # char.  # as commands are read into the shell, no need to export the   # shell variable ${your_backup_location} (see below)  ) # exit subshell, so we are back in start directory. done  

и readme.txt формат должен быть текстовым файлом с комментариями оболочки (объясняющим в комментариях, что нужно сделать), перемежающимся командами оболочки для выполнения:

 # Date: 2021-08-12 # Applicable Version: xx.x # Description: Quick summary of files  # Steps to apply: # 1. move the following files into a backup location # * xdir1/xdir2/xdir3/xdir4/filename-*.jar  mv filename-*.jar ${your_backup_location} # * xdir1/xdir2/xdir3/xdir4/filename1-*.jar  mv filename-*.jar ${your_backup_location} # 2. done. work completed.  

Таким образом, вы запустите подобласть в каждом каталоге, в котором у вас есть readme.txt файл. Вы можете указать множество фильтров по find команде, поэтому старайтесь выводить только то, что необходимо для выполнения какой-то реальной работы, и не пытайтесь создавать подобласть для каждого подкаталога просто для того, чтобы ничего не делать. И не используйте find каждый раз просто спускаться на один уровень, так как у вас будет много find запущенных процессов, которые почти ничего не будут делать.

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