"foo.date.bar" 형식의 이름을 가진 일련의 파일이 있습니다. 여기서 "date"는 6자리 필드입니다(예: 310715).
예를 들어
foo.310715.bar
foo.260815.bar
foo.110815.bar
foo.040815.bar
내 스크립트가 그 중 일부를 삭제할 수 있도록 파일 메타데이터가 아닌 파일 이름의 날짜를 기준으로 날짜 순서로 정렬하고 싶습니다. 일반적으로 저는 이 작업을 Python이나 PHP에서 쉽기 때문에 수행하지만 Bash에서 수행하는 방법을 배우려고 노력하고 있습니다. 처음으로 명령을 사용해 보았습니다.
for f in $( find $dir -type f | sort -r -t. -k 2 ); do
echo $f
done
그런데 두 번째 열을 숫자순이나 알파벳순으로 정렬하는 것은 소용이 없고 날짜순으로 정렬해야 한다는 것을 깨달았습니다. sort
6자리 필드를 날짜로 처리하는 방법이나 3개의 2자리 열로 처리하는 방법을 알 수 있는 방법이 없는 것 같습니다 . 다음 단계는 6자리 필드를 구문 분석할 수 있는 것으로 바꾸는 것과 유사한 sed
것을 사용하는 것인지 궁금합니다 .tr
sort
도움을 주셔서 미리 감사드립니다.
MB
귀하의 훌륭한 답변에 감사드립니다. 나는 그들로부터 많은 것을 배웠습니다.
답변1
이는 bash 배열의 오용입니다. 타임스탬프를 분리하고 YYMMDD 순서로 배열 항목을 생성한 다음 배열을 순서대로 인쇄합니다.
declare -a array
for file in foo.*.bar
do
[[ $file =~ foo.([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2}).bar ]] && \
{
index="${BASH_REMATCH[3]}${BASH_REMATCH[2]}${BASH_REMATCH[1]}"
array[$index]="$file"
}
done
for index in "${array[@]}"
do
echo $index
done
# or
printf "%s\n" ${array[@]}
답변2
GNU 또는 FreeBSD를 사용하는 경우 sort
또는 옵션을 사용하여 처음 사용한 후 날짜 형식을 바꿀 수 있습니다 -V
(그런 다음 날짜 형식을 다시 다시 변경).--version-sort
sed
sed
ls -1 |
sed -E -e 's/^(.*\.)(..)(..)(..)(.*)$/\1\4\3\2\5/' |
sort -V |
sed -E -e 's/^(.*\.)(..)(..)(..)(.*)$/\1\4\3\2\5/'
이상적으로는 유용한 날짜 형식을 갖도록 파일 이름을 바꾸는 것이 좋습니다. 예를 들어 Perl 이름 바꾸기 유틸리티를 사용하는 경우 prename
:
$ prename -v 's/^(.*\.)(..)(..)(..)(.*)$/$1$4$3$2$5/' *
foo.040815.bar renamed as foo.150804.bar
foo.110815.bar renamed as foo.150811.bar
foo.260815.bar renamed as foo.150826.bar
foo.310715.bar renamed as foo.150731.bar
$ ls -1 | sort -V
foo.150731.bar
foo.150804.bar
foo.150811.bar
foo.150826.bar
(대부분의 작업과 달리 prename
이 작업은 되돌릴 수 있습니다. 필요한 경우 다시 실행하여 원래 이름으로 다시 바꿀 수 있습니다.)
답변3
다음 파이프 시퀀스는 먼저 sed
형식의 파일 이름을 로 변경하는 데 사용됩니다. 형식이 변경된 출력은 "|"가 필드 구분 기호로 사용되어 먼저 YY( )로 정렬된 다음 MM( )으로 정렬됩니다. ( ). 그런 다음 정렬된 출력은 파일 이름이 원래 형식으로 다시 변환되는 위치로 다시 파이프됩니다.*.DDMMYY.*
*|DD|MM|YY|*
sort
-k4n
-k3n
-k2n
sed
*.DDMMYY.*
sed 's/\.\([[:digit:]]\{2\}\)\([[:digit:]]\{2\}\)\([[:digit:]]\{2\}\)\./|\1|\2|\3|/' | \
sort -t'|' -k4n -k3n -k2n | \
sed 's/|\([[:digit:]]\{2\}\)|\([[:digit:]]\{2\}\)|\([[:digit:]]\{2\}\)|/.\1\2\3./'
다음 파일 예시를 사용하세요.
$ ls *bar -1
abc.291015.bar
abc.291115.bar
abc.291215.bar
abc.301215.bar
foo.040815.bar
foo.150115.bar
foo.150914.bar
foo.260815.bar
foo.301216.bar
foo.310715.bar
xyz.010113.bar
이 시퀀스는 다음과 같은 결과를 생성합니다.
xyz.010113.bar
foo.150914.bar
foo.150115.bar
foo.310715.bar
foo.040815.bar
foo.260815.bar
abc.291015.bar
abc.291115.bar
abc.291215.bar
abc.301215.bar
foo.301216.bar