Я пытаюсь переименовать каждый access.log.gz
файл (примечание: точное имя файла, не "начинаясь" или "содержащий") найденный в /home/*/logs
кому: date-access.log.gz
в той же папке.
for file in /home/*/logs/access.log.gz
do
mv -v "$file" /home/*/logs/old/`date +\%G-\%m-\%d`"-access.log.gz"
done
Конечно, я добираюсь /home/*/logs/2014-09-08-access.log.gz - No such file or directory
. Как я могу звонить *
пути назад? Каждый файл должен быть переименован и перемещен в/old/subdir исходной папки. Я попробовал
mv -v "$file" /home/`$1`/logs/old/`date +\%G-\%m-\%d`"-access.log.gz"
... но не работал.
Использовать find
(Как может я использовать найти команду более эффективно?).
find /home/ -ipath */logs/access.log.gz
Это должно найти все файлы, Вы интересуетесь и печатаете их. Вы могли включить это в свой сценарий, но, вероятно, легче позволить find
сделайте всю тяжелую работу.
find /home/ -ipath */logs/access.log.gz -execdir mv "{}" "old/`date +\%G-\%m-\%d`-access.log.gz" \;
Функции find
мы используем, вот:
-ipath
шаблоны соответствий в найденных именах файлов. Вы могли также использовать -name
если Вы знали наверняка существует только один access.log.gz файл в каждом подпути (-name access.log.gz
).-execdir
выполняет данную команду на каждом найденном файле, от подкаталога, содержащего подобранный файл. Это эквивалентно выполнению cd
туда, где каждый файл и затем выполнение команды там. В этом случае это сохраняет большую логику управления путем. Найденным файлом заменяют {}. Заметьте также, что "старый" дан как относительный путь (поскольку Вы сказали это old/
существует в logs/
)Просто разделите и повторно соберитесь $file
поскольку Вы выполняете итерации по файлам соответствия: ${file%/*}
дает Вам $file со всем после последнего /
удаленный, и ${file##*/}
дает Вам $file со всем перед последним /
удаленный; взятый вместе ${file%/*}/old/$date-${file##*/}
даст Вам "новое" соответствие имени файла $file
.
По-видимому, дата не изменится в ходе запущения Вашего скрипта, таким образом, не будет никакого смысла в вызове date
для каждого файла; скорее сохраните дату в переменной однажды и затем используйте это во время цикла: date=$(date '+%G-%m-%d')
. (Обратите внимание, что современные сценарии должны использовать $(...)
вместо обратных галочек. Также отметьте это %
не "специальный" символ и так не нуждается в заключении в кавычки или выходе, хотя как хорошую практику целая строка формата должна быть заключена в кавычки.)
Если у Вас есть новая версия Bash, можно избежать подоболочки полностью при помощи printf -v date '%(%G-%m-%d)T' -1
вместо этого.
Вы могли бы также найти полезным использовать shopt -s globstar
так, чтобы можно было искать на произвольную глубину в каталогах, и shopt -s nullglob
так, чтобы несопоставленный шарик (подстановочный знак) ни до "чего" не расширялся вместо исходного шаблона шарика.
При помещении их всех вместе мы добираемся:
shopt -s globstar nullglob
date=$( date '+%G-%m-%d' )
for file in /home/*/logs/**/access.log.gz
do
target=${file%/*}/old/$date-${file##*/}
mv -vi "$file" "$target"
done
Если Вы имеете , установленный zsh, использует zmv
. В сценарии:
#!/bin/zsh
autoload zmv
zmv '/home/*/logs/access.log.gz' '$f:h/`date +\%G-\%m-\%d`-$f:t'
На zsh командной строке, помещенной autoload zmv
в Вашем ~/.zshrc
и выполненный, что последняя строка в командной строке.