
나는 많은 수의 이미지 파일을 가지고 작업해왔습니다. 그 중 일부는 1000개가 넘는 디렉터리에 분산되어 있는 모든 이미지 파일 형식을 하나의 디렉터리로 직접 이동하는 것이었습니다. 이름은 똑같지만 실제로는 다른 사진이 많았습니다. 이를 위해 다음과 같은 한 줄짜리 코드를 사용했습니다.
find . -type f -exec mv --backup=t '{}' /media/DATA-HDD/AllImages \;
같은 이름을 가진 모든 이미지를 덮어쓰는 대신 숨겨진 백업 파일을 만들도록 이 방법을 사용했습니다. 매우 잘 작동했지만 이제 해결해야 할 또 다른 문제가 생겼습니다.
물론 저는 다음과 같은 타일을 많이 가지고 있습니다.
DSC_0616.NEF
DSC_0616.NEF.~1~
DSC_0616.NEF.~2~
내가 하려는 것은 파일 이름에 백업 번호를 접미사로 추가하여 숨겨진 파일의 이름을 바꾸는 명령(또는 스크립트)을 실행하고 .~[bu#]~를 제거하여 고유하게 만드는 것입니다. 파일 이름이 있고 숨김이 없습니다. 따라서 다음과 같습니다.
DSC_0616.NEF
DSC_0616_1.NEF
DSC_0616_2.NEF
나는 이것을 직접 시도하기 위해 연구하는 데 두 시간 중 더 많은 시간을 보냈지만 주제에 대한 내 지식 영역 내에서 거기에 도달하는 데 도움이 될 수 있는 어떤 것도 실제로 찾을 수 없습니다.
답변1
위에서 설명한 대로 모든 이름이 일관되게 지정되어 있다고 확신하는 한 일부 정규식은 쉘 스크립트를 통해 작업을 완료할 수 있습니다.
#!/bin/bash
# sets the file separator to be only newlines, in case files have spaces in them
IFS=$'\n'
for file in $(find . -type f); do
# parses just the number(s) between two tildes, and only at the end of the file
number=$(echo $file | grep -Eo "~[0-9]+~$" | sed s/'~'/''/g)
# if no match found, assume this is a "base" file that does not need to be renamed
if [ "$number" == "" ]; then
continue
fi
# parses the file name through "NEF", then deletes ".NEF"
filename=$(echo $file | grep -Eio "^.+\.NEF" | sed s/'\.NEF'/''/g )
if [ "$filename" == "" ]; then
continue
fi
mv -v $file $(echo "$filename"_"$number.NEF")
# if anything went wrong, exit immediately
if [ "$?" != "0" ]; then
echo "Unable to move file $file"
exit 1
fi
done
이는 디렉토리를 통해 내려가는 경우에도 작동합니다. 스크립트를 배치하고 프로젝트 디렉토리 트리의 상단에 작업 디렉토리를 사용하여 실행하면 됩니다. 제공한 것과 같은 예제 파일을 사용하여 실행:
###@###:~/project$ find . -type f
./DSC_0616.NEF.~8~
./DSC_0616.NEF.~5~
./DSC_0616.NEF.~1~
./DSC_0616.NEF.~7~
./DSC_0616.NEF.~3~
./DSC_0616.NEF.~4~
./DSC_0616.NEF.~9~
./DSC_0616.NEF.~2~
./DSC_0616.NEF.~6~
./lower_dir/DSC_0616.NEF.~8~
./lower_dir/DSC_0616.NEF.~5~
./lower_dir/DSC_0616.NEF.~1~
./lower_dir/DSC_0616.NEF.~7~
./lower_dir/DSC_0616.NEF.~3~
./lower_dir/DSC_0616.NEF.~4~
./lower_dir/DSC_0616.NEF.~9~
./lower_dir/DSC_0616.NEF.~2~
./lower_dir/DSC_0616.NEF.~6~
스크립트를 실행한 후:
###@###:~/project$ find . -type f
./DSC_0616_1.NEF
./DSC_0616_3.NEF
./DSC_0616_7.NEF
./DSC_0616_5.NEF
./DSC_0616_2.NEF
./DSC_0616_9.NEF
./DSC_0616_6.NEF
./DSC_0616_8.NEF
./DSC_0616_4.NEF
./lower_dir/DSC_0616_1.NEF
./lower_dir/DSC_0616_3.NEF
./lower_dir/DSC_0616_7.NEF
./lower_dir/DSC_0616_5.NEF
./lower_dir/DSC_0616_2.NEF
./lower_dir/DSC_0616_9.NEF
./lower_dir/DSC_0616_6.NEF
./lower_dir/DSC_0616_8.NEF
./lower_dir/DSC_0616_4.NEF
답변2
의견에서 OP는 .NEF뿐만 아니라 모든 확장 프로그램에서 작동하는 솔루션을 요청했는데 저도 같은 문제를 겪었습니다. : 피
다음은 첫 번째 답변보다 좀 더 현대적인 Bashism을 갖춘 것입니다.
#!/usr/bin/env bash
# Renames the $1 directory's backup files (produced by `cp` or `mv` with the
# option `--backup=numbered`) such that "foo.png.~17~" becomes "foo_17.png"
function rename_backups()
{
for THING in "${1}"/*
do
if [[ -f "${THING}" &&
"${THING}" =~ ^.+\/+.+\..+~([0-9]+)~$ ]] # Take "foo.png.~17~".
then
# Get the "17".
local BACKUP_NUMBER=${BASH_REMATCH[1]}
# Remove the "~17~", leaving "foo.png".
local SANS_BACKUP_NUMBER="${THING%.*}"
# Get the filename, "foo", and the extension, "png".
local FILENAME="${SANS_BACKUP_NUMBER%.*}"
local EXT="${SANS_BACKUP_NUMBER##*.}"
# Rename to "foo_17.png".
local NEW_NAME="${FILENAME}_${BACKUP_NUMBER}.${EXT}"
while [[ -f "${NEW_NAME}" ]]
do
# If "foo_17.png" already exists for some reason, keep
# increasing the number until we find an unused one.
((++BACKUP_NUMBER))
NEW_NAME="${FILENAME}_${BACKUP_NUMBER}.${EXT}"
done
mv --no-clobber "${THING}" "${NEW_NAME}"
fi
done
}
rename_backups your/backup/directory/here/
아래 버전도 지원합니다.확장자 없음파일:
#!/usr/bin/env bash
# Renames the $1 directory's backup files (produced by `cp` or `mv` with the
# option `--backup=numbered`) such that:
# - "foo.png.~17~" becomes "foo_17.png"
# - "bar.~17~" becomes "bar_17"
function rename_backups()
{
for THING in "${1}"/*
do
# We'll either have a file like "foo.png.~17~" or "bar.~17~".
if [[ -f "${THING}" && "${THING}" =~ ^.+~([0-9]+)~$ ]]
then
# Get the "17".
local BACKUP_NUMBER=${BASH_REMATCH[1]}
# Remove the "~17~", leaving, e.g., "foo.png".
local SANS_BACKUP_NUMBER="${THING%.*}"
# Get the filename, "foo", and the extension, "png".
local FILENAME="${SANS_BACKUP_NUMBER%.*}"
local EXT="${SANS_BACKUP_NUMBER##*.}"
if [[ "${FILENAME}" == "${SANS_BACKUP_NUMBER}" ]]
then
# This is a "bar.~17~" case, so rename to "bar_17".
local NEW_NAME="${FILENAME}_${BACKUP_NUMBER}"
while [[ -f "${NEW_NAME}" ]]
do
# If "bar_17" already exists for some reason, keep
# increasing the number until we find an unused one.
((++BACKUP_NUMBER))
NEW_NAME="${FILENAME}_${BACKUP_NUMBER}"
done
else
# This is a "foo.png.~17~" case, so rename to "foo_17.png".
local NEW_NAME="${FILENAME}_${BACKUP_NUMBER}.${EXT}"
while [[ -f "${NEW_NAME}" ]]
do
((++BACKUP_NUMBER))
NEW_NAME="${FILENAME}_${BACKUP_NUMBER}.${EXT}"
done
fi
mv --no-clobber "${THING}" "${NEW_NAME}"
fi
done
}
rename_backups your/backup/directory/here/