Использование mv для перемещения в другой каталог и немедленного переименования

Использование mv для перемещения в другой каталог и немедленного переименования

Я хотел бы узнать все файлы размером более 100 Мб, к которым не было доступа в течение последнего месяца, и я успешно написал:

find / -size +100M -atime +30

И теперь я хочу переместить эти файлы в папку с именем /big-not-used, изменив ее имя следующим образом: file_nameYYYYMMDDгде file_name — это имя исходного файла, а YYYYMMDD — это сегодняшняя дата в формате год месяц день. Например, film.mkvидет в/big-not-used/film.mkv20161031

Мое предложение было бы таким:

find / -size +100M -atime +30 -exec mv {} /big-not-used/... \;

Но я не знаю, как добавить сегодняшнюю дату к имени файла. Я обнаружил, что date +%Y-%m-%dвыводит: 2016-10-31что полезно. Теперь возникает вопрос, как получить имя этого файла? Следующее: https://stackoverflow.com/questions/5456120/how-to-only-get-file-name-with-linux-find

... -exec basename {} \;

Может быть?:

find / -size +100M -atime +30 -exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;

Но он выдает ошибку, потому что basename отвечает полным путем к файлу вместо его имени, которое я бы использовал:

${var##/*/}

чтобы получить имя файла, но вопрос в том, как мне вставить то, что basename {}отвечает, в переменную var в предыдущем выражении!?.

Может быть?

$(${$(basename {})##/*/})

Но это говорит о синтаксической ошибке возле неожиданного '}'...

решение1

Вы были близки к:

find / -size +100M -atime +30 \
  -exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;

$(...)Но без кавычек происходит расширение оболочки конструкцийперед findвыполнением команды. Другими словами, учитывая приведенную выше командную строку, которая на самом деле будет выполнена, это:

find / -size +100M -atime +30 \
  -exec mv {} /big-not-used/{}2016-10-30 \;

Потому что результат $(basename {})— это просто {}, и вот почему вы получаете полный путь. Попробуйте это вместо этого:

find / -size +100M -atime +30 \
  -exec sh -c 'mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;

Для проверки вы можете заменить mvна echo mv, например так:

find / -size +100M -atime +30 \
  -exec sh -c 'echo mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;

...и посмотрите, как выглядят сгенерированные команды.

решение2

Я немного улучшил решение Ларка, чтобы сделать только один shвызов:

find / -size +100M -atime +30 -exec sh -c \
  'for f do mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"; done' sh {} +

Либо shвообще без звонков:

while IFS= read -r f; do
  mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"
done < <(find / -size +100M -atime +30)

(Последнее при условии, что в именах файлов нет символов новой строки.)

Для отладки вам может понадобиться добавить -v( mvесли поддерживается).

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