저는 이곳에 처음 왔으니 양해해 주시기 바랍니다.
수천 개의 파일이 포함된 디렉토리가 있습니다. 파일 이름은 항상 1~2개의 문자로 시작하고 그 뒤에 밑줄 "_" 앞에 4개의 문자가 옵니다. 각 모드의 파일 개수는 다를 수 있으며 파일 이름에서 밑줄 뒤의 부분이 변경됩니다.
견본:
Parentdir:
->AA01_*.pdf
->AA01_*.html
->AA01_*.txt
...
->ZZ99_*.pdf
->ZZ99_*.html
->ZZ99_*.txt
...
->A001_*.pdf
->A001_*.html
->A001_*.txt
...
->Z999_*.pdf
->Z999_*.html
->Z999_*.txt
파일 이름의 문자만 사용하여 새 디렉터리를 만들고 해당 문자로 시작하는 파일로 채우는 명령을 실행하고 싶습니다. 대상 디렉터리에 같은 이름의 파일(원본 디렉터리의 업데이트된 파일)이 있으면 최신 파일을 유지하고 싶습니다. 그래서:
New dir/files:
->AA
AA01_*.pdf
AA01_*.html
AA01_*.txt
...
->ZZ
ZZ99_*.pdf
ZZ99_*.html
ZZ99_*.txt
...
->A
A001_*.pdf
A001_*.html
A001_*.txt
...
->Z
Z999_*.pdf
Z999_*.html
Z999_*.txt
이것이 달성될 수 있습니까?
감사해요!
답변1
파일 세트를 탐색합니다. 문자 접두어를 선택하세요. 디렉터리를 만들고(필요한 경우) 파일을 해당 디렉터리로 이동합니다.
#!/bin/sh
for item in *
do
if [ -f "$item" ]
then
prefix="$(echo "$item" | sed 's/[^A-Z].*//')"
echo mkdir -p "$prefix"
echo mv "$item" "$prefix/"
fi
done
echo
접두사를 제거 mkdir
하면 mv
만족스러울 때 원하는 대로 작동합니다.
답변2
사용진주 rename
유틸리티( 일부 Linux 배포판에서는 prename
라고도 함 file-rename
) perl-rename
:
rename -n 'if (m/^(\w{1,2}?)(\d{2,}_.*)/) {mkdir $1; $_ = "$1/$1$2"}' *
참고: 이것은 작동합니다오직Perl 기반 이름 바꾸기 유틸리티를 사용하십시오. rename -V
(or prename -V
또는 or)를 실행하여 file-rename -V
설치 여부를 확인할 수 있습니다 perl-rename -V
. perl 또는 이 언급되면 File::Rename
이는 의 Perl 버전입니다 rename
. 그렇지 않으면 완전히 다를 rename
수 있습니다util-linux
호환되지 않는기능 및 명령줄 옵션. 이것은 것이다아니요util-linux의 이름 바꾸기(또는 다른 버전의 이름 바꾸기 - it)를 사용하십시오.필요펄 이름 바꾸기)
이는 일치하는 각 파일 이름(탐욕적이지 않은 일치)의 처음 한두 개의 "단어" 문자를 디렉토리로 사용한 다음 디렉토리를 생성하고 파일 이름을 디렉토리로 바꿉니다. "단어" 문자( \w
)는 다음과 같이 정의됩니다 man perlre
.
""단어" 문자 일치(영숫자와 "_", 기타 연결 구두점 및 유니코드 마커)"
이것이 원하는 것이 아니라면 알파벳 문자나 대문자만 사용하는 [[:alpha:]]{1,2}?
대신에 패턴을 최적화할 수 있습니다.\w{1,2}?
[[:upper:]]{1,2}
이 \d
번호. 당신이 허락하고 싶다면어느밑줄 앞에 문자를 사용하십시오 \w
. 또는 [[:alnum:]]
알파벳과 숫자만 허용하려면 를 사용하십시오.
전체 패턴(1~2개의 "단어" 문자, 그 뒤에 최소 두 자리 숫자, 그 뒤에 밑줄)과 일치하지 않는 파일 이름은 영향을 받지 않습니다.
참고: -n
옵션을 사용하면 연습 실행 작업이 수행됩니다. 내용만 표시됩니다회의하고 있지만 실제로는 하지 않습니다. 요구 사항을 충족한다고 확신하면 제거합니다 (또는 자세한 출력으로 -n
교체 ).-v
예를 들어 다음 설정 스크립트가 있다고 가정해 보겠습니다.
#!/bin/bash
for i in A AA Z9 ZZ ; do
for j in {01..10} ; do
touch "$i${j}_.txt"
done
done
# anomaly
touch A1001_.txt
$ ./setup.sh
$ ls
A01_.txt A02_.txt A03_.txt A04_.txt A05_.txt A06_.txt A07_.txt A08_.txt
A09_.txt A1001_.txt A10_.txt AA01_.txt AA02_.txt AA03_.txt AA04_.txt AA05_.txt
AA06_.txt AA07_.txt AA08_.txt AA09_.txt AA10_.txt setup.sh* Z901_.txt
Z902_.txt Z903_.txt Z904_.txt Z905_.txt Z906_.txt Z907_.txt Z908_.txt
Z909_.txt Z910_.txt ZZ01_.txt ZZ02_.txt ZZ03_.txt ZZ04_.txt ZZ05_.txt
ZZ06_.txt ZZ07_.txt ZZ08_.txt ZZ09_.txt ZZ10_.txt
Perl 이름 바꾸기 스크립트를 실행한 후:
$ rename 'if (m/^(\w{1,2}?)(\d{2,}_.*)/) {mkdir $1; $_ = "$1/$1$2"}' *
$ ls */*
A/A01_.txt A/A02_.txt A/A03_.txt A/A04_.txt A/A05_.txt A/A06_.txt
A/A07_.txt A/A08_.txt A/A09_.txt A/A1001_.txt A/A10_.txt AA/AA01_.txt
AA/AA02_.txt AA/AA03_.txt AA/AA04_.txt AA/AA05_.txt AA/AA06_.txt
AA/AA07_.txt AA/AA08_.txt AA/AA09_.txt AA/AA10_.txt Z/Z901_.txt
Z/Z902_.txt Z/Z903_.txt Z/Z904_.txt Z/Z905_.txt Z/Z906_.txt Z/Z907_.txt
Z/Z908_.txt Z/Z909_.txt Z/Z910_.txt ZZ/ZZ01_.txt ZZ/ZZ02_.txt ZZ/ZZ03_.txt
ZZ/ZZ04_.txt ZZ/ZZ05_.txt ZZ/ZZ06_.txt ZZ/ZZ07_.txt ZZ/ZZ08_.txt
ZZ/ZZ09_.txt ZZ/ZZ10_.txt
답변3
포럼에 오신 것을 환영합니다, 지카님!
나는 제안하고 싶다organize
- 인내심이 있다면 yaml
주어진 위치에서 파일을 검색하고, 이름을 바꾸고, 이동하고, 정렬하고, 이름을 지정할 수 있는 스크립트를 만들 수 있습니다! 나는 그것을 직접 사용합니다. 여러분이 Linux에 얼마나 익숙하신지는 모르겠지만 Git에는 필요한 모든 것을 매우 이해하기 쉬운 방식으로 설명하는 문서가 있습니다.