이름을 기준으로 파일을 찾아 이동하고 동시에 이름을 바꿉니다.

이름을 기준으로 파일을 찾아 이동하고 동시에 이름을 바꿉니다.

연도를 기준으로 이름이 지정된 디렉토리가 있고 테마 코드를 기반으로 하는 PDF 파일이 포함되어 있다고 가정해 보겠습니다.

ls출력은 다음과 같습니다

$ ls -l
total 32
drwxrwxrwx 1 root root 4096 Apr  8 08:52 May-June-2011
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Nov-Dec-2011
drwxrwxrwx 1 root root 4096 Apr  8 20:36 Summer-2012
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Summer-2013
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Summer-2014
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Winter-2012
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Winter-2013
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Winter-2014

각 디렉토리에는 제목 코드에 따른 pdf 파일이 포함되어 있습니다.

ls -l May-June-2011/
total 808
-rwxrwxrwx 1 root root 104193 May  1  2011 161901.pdf
-rwxrwxrwx 1 root root 103380 May  1  2011 161902.pdf
-rwxrwxrwx 1 root root 115664 May  1  2011 161903.pdf
-rwxrwxrwx 1 root root  88953 May  1  2011 161904.pdf
-rwxrwxrwx 1 root root 179268 May  1  2011 161905.pdf
-rwxrwxrwx 1 root root 116158 May 24  2011 161906.pdf
-rwxrwxrwx 1 root root 106033 May  1  2011 161907.pdf

즉, 모든 디렉토리에는16190{1..7}.pdf


161901.pdf이제 언급된 모든 디렉터리의 모든 항목을 특정 디렉터리(예: xyz)로 이동하고 이름을 상위 폴더의 name.pdf로 바꾸려고 한다고 가정합니다 .

설명하다:-

다음은 그 목록입니다 161901.pdf.

$ find -name 161901.pdf
./May-June-2011/161901.pdf
./Nov-Dec-2011/161901.pdf
./Summer-2012/161901.pdf
./Summer-2013/161901.pdf
./Summer-2014/161901.pdf
./Winter-2012/161901.pdf
./Winter-2013/161901.pdf
./Winter-2014/161901.pdf

./May-June-2011/161901.pdf새로운 이름(파일이 위치한 디렉토리 이름)으로 옮겨 졌으면 좋겠습니다 . 즉, 다음으로 이동xyzMay-June-2011.pdf./May-June-2011/161901.pdf./xyz/May-June-2011.pdf

마찬가지로 , ./Nov-Dec-2011/161901.pdfto 등 ( to 까지 )../xyz/Nov-Dec-2011.pdf./Summer-2012/161901.pdf./xyz/Summer-2012.pdf./Winter-2014/161901.pdf./xyz/Winter-2014.pdf

예상되는 출력 ls xyz은 다음과 같습니다.

$ls xyz
May-June-2011.pdf
Nov-Dec-2011.pdf
Summer-2012.pdf
Summer-2013.pdf
Summer-2014.pdf
Winter-2012.pdf
Winter-2013.pdf
Winter-2014.pdf

어떻게 해야 하나요? (루프 또는 기타 방법 find -exec또는 사용 방법)

답변1

펄 모듈유니코드::싸움다음과 같은 매우 유용한 스크립트가 함께 제공됩니다.이름을 바꿔라(이 이름은 Linux의 표준과 충돌하므로 이는 불행한 일입니다 rename(1).) 그것으로 당신은 다음과 같은 일을 할 수 있습니다 :

mkdir xyz
find . -name '*.pdf' -print0 | \
    rename -0 's!^\.!xyz!;  s!/[^/]*\.pdf$!.pdf!'

Perl이 없어도 일부 쉘 파이핑을 사용하여 동일한 작업을 수행할 수 있습니다.

mkdir xyz
find . -name '*.pdf' | sed 's/^/mv /' >src
find . -name '*.pdf' | sed 's!^\./!xyz/!; s!/[^/]*\.pdf$!.pdf!' >dest
join src dest | sh -
rm -f src dest

그리고 다른 사람들이 금방 지적할 것이라고 확신하지만 <(...)프로세스 대체를 사용하여 한 줄에 넣을 수도 있습니다. 그러나 이것이 상황을 더 명확하게 만드는지는 확실하지 않습니다. 오늘날의 컴퓨터는 더 자세한 구문을 사용할 수 있을 만큼 강력합니다. ;)

답변2

find디렉터리 트리를 재귀적으로 탐색할 필요가 없을 때는 거의 유용하지 않습니다. 여기서는 간단한 루프와 쉘 와일드카드로 충분합니다.

for x in */161901.pdf; do
  mv -- "$x" "xyz/${x%/*}.pdf"
done

renameprename또는 Debian, Ubuntu 및 그 파생 제품( 다른 배포판의 Linux 명령이 아닌 Arch의 경우 rename) 에서 Perl 기반 명령을 사용합니다 .

rename 's!/.*!!; $_="xyz/$_.pdf"' */161901.pdf

또는 zsh를 사용하세요.

autoload -U zmv
zmv '(*)/161901.pdf' 'xyz/$1.pdf'

답변3

find -print한 가지 방법은 파일 목록을 가져와서 다음 명령 awk과 같이 원하는 대로 변환할 수 있는 위치 로 파이프하는 것입니다.cp

$ find -name 161901.pdf -print | awk -v TARGET=xyz -F'/' '{ printf "cp %s %s/%s.pdf\n", $0, TARGET, $2; }'
cp ./May-June-2011/161901.pdf xyz/May-June-2011.pdf
cp ./Nov-Dec-2011/161901.pdf xyz/Nov-Dec-2011.pdf

그런 다음 실행을 위해 셸로 파이프될 수 있습니다.

find -name 161901.pdf -print | awk -v TARGET=xyz -F'/' '{ printf "cp %s %s/%s.pdf\n", $0, TARGET, $2; }' | sh 

답변4

당신이 가지고 있다면이름 바꾸기/이름 바꾸기주문하다

find -name 161901.pdf -exec prename -n 's!/!-!g; s!\W*!xyz/!' {} +

-n보시고 마음에 드시면 삭제해주세요.

(Larry Wall과 Robin Barker의 이름은 perl.deb 패키지와 함께 설치되며 Brian d Foy의 Unicode::Tussle이름 변경도 가능합니다.)

관련 정보