폴더에 수천 개의 텍스트 파일이 있고 특정 방식으로 이름이 지정됩니다.
예를 들어:
Image_234_Data_7778_n0.txt
Image_234_Data_7778_n1.txt
Image_234_Data_7778_n2.txt
Image_954_Data_4478_n0.txt
Image_954_Data_4478_n1.txt
Image_954_Data_4478_n2.txt
Image_104_Data_9878_n0.txt
Image_104_Data_9878_n1.txt
Image_104_Data_9878_n2.txt
등...
내용이 다음과 같아야 하는 소스 파일(파일 이름을 바꾸고 "어느 것이 무엇인지" 추적하는 데 사용됨)을 만들고 싶습니다.
1_1.txt:Image_234_Data_7778_n0.txt
1_2.txt:Image_234_Data_7778_n1.txt
1_3.txt:Image_234_Data_7778_n2.txt
2_1.txt:Image_954_Data_4478_n0.txt
2_2.txt:Image_954_Data_4478_n1.txt
2_3.txt:Image_954_Data_4478_n2.txt
3_1.txt:Image_104_Data_9878_n0.txt
3_2.txt:Image_104_Data_9878_n1.txt
3_3.txt:Image_104_Data_9878_n2.txt
등...
누구든지 나를 위해 이 작업을 수행할 코드를 작성하는 데 도움을 줄 수 있습니까?
답변1
나는 귀하의 파일 이름이 숫자로 끝나지 않고 일련의 숫자인 임의의 텍스트 XXXXNNN.txt
형식 이고 동일한 XXX로 그룹화하기를 원한다고 가정합니다.XXXX
NNN
전략: 사전순으로 파일을 반복하고 XXXX 섹션이 변경되는 시기를 감지합니다. 각 그룹에 대해 새 이름을 생성합니다. 한 가지 사소한 문제는 NNN 부분이 가변 너비인 경우 사전순으로 정렬되지 않는다는 것입니다. NNN=10은 NNN=1과 NNN=2 사이에 나타납니다.
current=
numbers=
i=0
for x in *.txt ''; do
stem=${x%.*}
n=${stem##*[!0-9]}
stem=${stem%$n}
if [ "$stem" != "$current" ]; then
for k in $(printf '%s\n' $numbers | sort -n); do
y=${i}_${k}.txt
echo mv "$current$k.txt" "$y"
done
current=$stem
numbers=$n
i=$((i+1))
else
numbers="$numbers $n"
fi
done
파일 이름 바꾸기, 파일에 정보 쓰기 echo mv
등 사용하려는 명령으로 바꿉니다 .mv
echo …
파일 이름을 바꾸고 이전 이름을 추적하는 대신 다음을 사용하는 것이 좋습니다.심볼릭 링크원래 이름과 단순화된 이름을 사용하여 파일에 액세스할 수 있습니다.
답변2
다음 파일을 포함하는 테스트 디렉터리를 만든 후:
Image_104_Data_9878_n0.txt, Image_104_Data_9878_n1.txt,
Image_234_Data_7778_n0.txt, Image_234_Data_7778_n1.txt,
Image_234_Data_7778_n2.txt, Image_954_Data_4478_n0.txt,
Image_954_Data_4478_n1.txt, Image_954_Data_4478_n2.txt
그런 다음 나는 다음을 수행했습니다.
printf %s\\n * | sort --debug -t_ -k2,2n -k5.2n,5.2n
결과 :
Image_104_Data_9878_n0.txt
___
_
__________________________
Image_104_Data_9878_n1.txt
___
_
__________________________
Image_234_Data_7778_n0.txt
___
_
__________________________
Image_234_Data_7778_n1.txt
___
_
__________________________
Image_234_Data_7778_n2.txt
___
_
__________________________
Image_954_Data_4478_n0.txt
___
_
__________________________
Image_954_Data_4478_n1.txt
___
_
__________________________
Image_954_Data_4478_n2.txt
___
_
__________________________
sort
예를 들어, 2cd로 구분된 필드에서 필드 시작부터 필드 끝까지의 숫자를 기준으로 주로 정렬하고, 5번째 필드의 두 번째 2cd 바이트를 기준으로 숫자를 기준으로 정렬하라는 지시를 받았습니다 . 나는 그것이 정확히 무엇을 하고 있는지 알려주기 위해 출력을 요청했습니다._
-k2,2n
-k5.2,5.2n
--debug
주로 필드 4, 주로 필드 2, 두 번째는 필드 5.2, 가장 중요하지 않은 것은 두 번째 필드로 쉽게 정렬할 수 있습니다. 귀하의 예에 제공된 순서에 대한 운율이나 이유를 확인할 수 없기 때문에 이렇게 말하는 것입니다. 귀하가 이를 다음과 같이 할당했다고 가정할 수 있습니다.
- 1_1:234/7778
- 2_1:954/4478
- 3_1:104/9878
...지금까지 정렬을 위한 적절한 명령을 작성하지 않았으므로 이를 수행하는 방법에 대한 조언이 필요할 수 있습니다. 이 가정을 바탕으로 나는 다음과 같이 할 것이다.
printf %s\\n * |
sort -t_ -k4,4n -k5.2n,5.2n |
nl -bp'_n0\.' -s_ |
sed 's/\(I[^.]*_n\)\(.*\)/\2:\1\2/;N
s/ *\([0-9]*_\)\(.*\n\) *\([^_]*I\)/\1\2\1\3/;P;D'
나는 이것이 당신이 찾고 있는 것과 매우 가까운 결과를 낳을 것이라고 생각합니다. 바라보다?
1_0.txt:Image_954_Data_4478_n0.txt
1_1.txt:Image_954_Data_4478_n1.txt
1_2.txt:Image_954_Data_4478_n2.txt
2_0.txt:Image_234_Data_7778_n0.txt
2_1.txt:Image_234_Data_7778_n1.txt
2_2.txt:Image_234_Data_7778_n2.txt
3_0.txt:Image_104_Data_9878_n0.txt
3_1.txt:Image_104_Data_9878_n1.txt
내가 지정했기 때문에 네 번째 필드를 기준으로 정렬되고 번호가 지정되지만 -k4,4n
지침 을 sort
쉽게 따를 수 있습니다 .-k2,2n
nl
이 명령은 문자열을 포함하는 줄에만 번호를 매기 도록 요구함으로써 작동합니다 _n0.
. sed
다음과 같이 출력을 받습니다.
1_Image_954_Data_4478_n0.txt
Image_954_Data_4478_n1.txt
Image_954_Data_4478_n2.txt
2_Image_234_Data_7778_n0.txt
Image_234_Data_7778_n1.txt
Image_234_Data_7778_n2.txt
3_Image_104_Data_9878_n0.txt
Image_104_Data_9878_n1.txt
...먼저 _n[0-9]*.txt
비트를 줄의 시작 부분에 복사하고, N
ext는 다음 줄을 가져옵니다. 패턴 공간이 다음과 같은 경우:
*num_.*\n [^_]*I
...이 시점에서 첫 번째 줄의 숫자 비트를 두 번째 줄에 추가합니다. 이 명령으로 생성된 텍스트 파일에서 이동 작업으로 이동하려면 다음을 수행할 수 있습니다.
sed 's/\([^:]*\):\(.*\)/$* \2 \1/' <txtfile |
sh -s -- echo mv
산출
mv Image_954_Data_4478_n0.txt 1_0.txt
mv Image_954_Data_4478_n1.txt 1_1.txt
mv Image_954_Data_4478_n2.txt 1_2.txt
mv Image_234_Data_7778_n0.txt 2_0.txt
mv Image_234_Data_7778_n1.txt 2_1.txt
mv Image_234_Data_7778_n2.txt 2_2.txt
mv Image_104_Data_9878_n0.txt 3_0.txt
mv Image_104_Data_9878_n1.txt 3_1.txt
쉘 프로세스에 대한 첫 번째 인수이기 때문에 방금 ed라고 표시되어 있지만 echo
방금 한 것처럼 이를 제거하고 실행하면 동일한 결과를 얻게 됩니다.
ls -m
1_0.txt, 1_1.txt, 1_2.txt, 2_0.txt, 2_1.txt, 2_2.txt, 3_0.txt, 3_1.txt
Gilles는 좋은 아이디어라고 생각하는 링크를 추천했지만, 개인적으로는 소프트 링크를 피하고 가능하다면 미러링된 하드 링크 디렉토리를 만들겠습니다. 거의 동일한 방식으로 이 작업을 수행할 수 있지만 ln
대신 를 사용하는 것이 좋습니다 mv
.
답변3
이와 같은 문제를 해결하는 한 가지 방법(특히 스크립팅에 능숙하지 않은 경우)은 스프레드시트를 사용하여 스크립트를 생성하는 것입니다. 재사용 가능한 스크립트를 작성하려는 경우 이는 좋은 방법이 아니지만 다른 방법으로 스크립트를 작성하는 방법을 배울 시간이 없는 사람들을 위한 일회성 작업에는 유용할 수 있습니다.
달성하려는 이름 바꾸기(또는 연결)는 a 앞의 모든 것을 a _n
앞의 단일 시퀀스 번호로 변경 _
하고 나머지는 _n
변경되지 않은 채로 두는 것 같습니다. 정확한 의도가 아닌 경우 스프레드시트 수식을 쉽게 수정할 수 있습니다.
예를 들어(가로 스크롤의 필요성을 줄이려면 파일 이름을 줄이세요):
A2 B2 C2 D2 E2
i234d7778_n0.txt =FIND("_n",A2) =LEFT(A2,B2) =D1+(C2<>C1) =D2&"_"&RIGHT(A2,LEN(A2)-B2-1)
i234d7778_n0.txt 10 i234d7778_ 1 1_0.txt
행 1이 아닌 행 2에서 시작하는 이유는 D2의 비교가 행 1로 진행되기 때문입니다. (대안은 첫 번째 행에 배치하는 것이지만 특별한 경우 D1은 행 1에 배치됩니다.)
D2의 표현식은 간단히 말해서 다음과 같습니다.=IF(C2=C1,D1,D1+1)
스프레드시트와 마찬가지로 파일 목록을 A열에 붙여넣은 다음 파일 수에 따라 B열부터 E열까지 반복합니다. 이름 바꾸기를 수행하는 스크립트를 생성하려면 "F" 또는 "G" 열을 추가하면 됩니다.
F2 G2
="mv "&A2&" "&E2 ="ln "&A2&" new-name-directory/"&E2
mv i234d7778_n0.tx 1_0.txt ln i234d7778_n0.tx new-name-directory/1_0.txt
F열과 G열은 실행 가능한 스크립트의 텍스트를 제공합니다.