파일 이름에서 특정 요소를 추출하는 방법은 무엇입니까?

파일 이름에서 특정 요소를 추출하는 방법은 무엇입니까?

다음 형식의 파일이 많이 있습니다.

2014-11-19.8.ext
2014-11-26.1.ext
2014-11-26.2.blah.ext
2014-11-26_3.ext
2014-11-26.4.stuff_here.ext
2014-12-03.1. could be anything.ext
2014-12-032b.ext
2014-11-26 613 adva.ext

내 목표는 전체 파일 목록을 반복하여 날짜 형식을 가져와 추가 처리를 위해 YYYY-MM-DD변수에 저장하는 것입니다 (내 경우에는 명령 YYYYMMDD에 푸시됩니다 ).touch

따라서 일반적으로 다음 정규식과 일치합니다.(\d{4})-(\d{2})-(\d{2}).*

그런 다음 를 사용하여 원하는 패턴을 얻었지만 / 에서 이 작업을 수행하는 $1$2$3방법을 잘 모르겠습니다 .bashzsh

쉘 스크립트에서 이를 어떻게 수행할 수 있습니까?

답변1

사용매개변수 확장

$ touch 2014-11-19.8.ext 2014-11-26.1.ext
$ for f in *.ext; do d="${f:0:4}${f:5:2}${f:8:2}"; echo "$d"; done
20141119
20141126
  • ${f:0:4}변수명인 index부터 시작하여 4자를 나타냅니다 0.f
  • echo "$d"귀하의 코드로 바꾸십시오 .

답변2

현재 디렉터리의 각 파일을 반복하고 파일 이름을 원하는 패턴과 비교하려면 날짜 조각이 포함된 변수를 설정하세요.

for f in *
do 
  [[ $f =~ ^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])(.*) ]] && 
  yourvar="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
done

이는 다음을 사용합니다.[[정규식 일치를 사용하는 bash 기능날짜 조각을 BASH_REMATCH 배열에 넣습니다.

답변3

다음 명령을 사용하여 대화식으로 이 작업을 수행할 수 있습니다 GNU sed.

$ sed 's/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}.*\)/\1\2\3/g' stuff.txt

여러 파일의 경우(동일한 디렉터리에 있고 해당 디렉터리에 고려되는 다른 파일이 없는 경우):

for file in *
do
    if [ -f "$file" ]
    then
          sed 's/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\).*/\1\2\3/g' "$file"
    fi
done

답변4

GNU Coreutils를 사용하면 다음이 표시됩니다.

$ date --date=2014-11-13 +"%Y%m%d"
20141113

하지만:

$ date --date=2014-11-130ABCJUNK +"%Y%m%d"
date: invalid date ‘2014-11-130ABCJUNK’

따라서 작업은 훨씬 간단합니다. YYYY-MM-DDetc각 파일 이름의 처음 10자를 추출하여 날짜 자체를 얻은 다음 이를 date다시 포맷하는 데 전달합니다.

그러나 GNU Coreutils를 사용하는 경우 정확히 동일한 옵션이 있으므로 해당 date명령을 건너뛸 수 있습니다 .touch--date=STRING

for file in * ; do
  date=${file%${file##??????????}} # chop all but first ten
  touch --date=$date -- "$file"
done

touch그런데 GNU Coreutils에 의존할 때 POSIX 이식 가능한 방식으로 10자 슬라이싱을 수행하는 이유는 무엇입니까?

for file in * ; do
  date=${file:0:10}
  touch --date=$date -- "$file"
done

관련 정보