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)

(후자는 파일 이름에 개행 문자가 없다고 가정합니다.)

디버깅을 위해 추가해야 할 수도 있습니다 -v( mv지원되는 경우).

관련 정보