mvを使用して別のディレクトリに移動し、すぐに名前を変更します。

mvを使用して別のディレクトリに移動し、すぐに名前を変更します。

私は+100Mbで、先月アクセスされなかったすべてのファイルを知りたいです。そしてうまく書いた:

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

一度だけ呼び出すようにLarkのソリューションを改善しました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)

(後者はファイル名に改行文字がないと仮定します.)

デバッグのために追加する必要があります-vmvサポートされている場合)。

関連情報