Bash копирует файлы из нескольких каталогов в несколько соответствующих резервных каталогов

Bash копирует файлы из нескольких каталогов в несколько соответствующих резервных каталогов

У меня есть несколько каталогов { dir1,dir2,dir3,dir4} на компьютере с Linux.

В каждом каталоге есть несколько файлов (с одинаковым расширением, скажем, .zip), которые я хочу скопировать в соответствующие каталоги { dir1-bck,dir2-bck,dir3-bck,dir4-bck}. Мне не нужно копировать всю папку, а только несколько файлов в каждой.

Как бы мне сделать так, чтобы файлы были скопированы из dir1/*.zip... dir1-bckдля списка предоставленных каталогов. В настоящее время я использую:

cp -r src/dir1/*.zip dest/dir1-bck/
cp -r src/dir2/*.zip dest/dir2-bck/
cp -r src/dir3/*.zip dest/dir3-bck/
cp -r src/dir4/*.zip dest/dir4-bck/

Это работает, но есть огромный потенциал для улучшения.

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

решение1

Вероятно, forцикл будет как раз правильным. Точная форма зависит от того, как названы эти каталоги. Это может быть:

cd src || exit 1
for d in "dir"{1..4}; do
   cp -r "$d"/*.zip "../dest/$d-bck/"
done

Примечания:

  • Хорошо работать изнутри src( cd src), так что переменная содержит строку, которую можно использовать в целевом пути без дополнительной обработки. Целевой путь был скорректирован путем добавления препина ../в этом случае, но в целом он может быть таким, как "/full/path/to/dest/$d-bck/".
  • Я цитировал dirна случай, если вы замените имя пробелами или чем-то подобным. Я заключил в двойные кавычки $dпо той же причине иболее.
  • Если *.zipэто файлы, то вам не нужны -r.

Альтернативно forстрока может быть такой:

for d in dir1 dir2 dir3 dir4; do

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

for d in *; do

Можно сделать несколько улучшений, например:

( cd src || exit 1
for d in *; do
   dst="../dest/$d-bck/"
   [ -d "$d" ] && mkdir -p "$dst" && cp -- "$d"/*.zip "$dst"
done )

Улучшения:

  • Весь код выполняется в подоболочке ( (…)), поэтому cdне повлияет на текущую оболочку, даже если вы вставите код в терминал. Если бы это был автономный скрипт (выполняемый, а не исходный), то подоболочка была бы неактуальна.
  • Проверяем, $dявляется ли это каталогом.
  • Мы пытаемся создать целевой каталог (на случай, если он не существует).
  • Мы продолжим работу cpтолько в том случае, если целевой каталог существует.
  • Мы используемдвойное тирев случае, если $dначинается с тире.

Возможные проблемы:

  • "$d"/*.zipможет расшириться до слишком большого количества элементов ( Argument list too long). Ваши исходные команды "неполны" таким же образом. Если в каждом каталоге "всего несколько файлов", то это не должно быть проблемой.
  • "$d"/*.zipможет не расширяться ( *остается буквальным). Это не должно навредить, но целевой каталог будет создан заранее. В таком случае может потребоваться дополнительная логика для подавления создания каталога.
  • Статус выхода всего фрагмента зависит только от последнего [ … && mkdir … && cp …. Вам нужна дополнительная логика, чтобы более ранние проблемы влияли на статус выхода.

Связанный контент