파일 이름의 날짜를 기준으로 파일을 폴더로 정렬하시겠습니까?

파일 이름의 날짜를 기준으로 파일을 폴더로 정렬하시겠습니까?

해결됨: 댓글의 업데이트를 참조하세요.

파일 이름에 날짜가 포함된 파일을 해당 날짜를 기준으로 폴더로 정렬하려고 합니다. 이러한 파일은 아래와 같이 파일 이름에 공백이 있었습니다. 오래된 파일도 있어서 정리해야 합니다.

일정 Fax_20180521121901.pdf

현재 우리가 받고 있는 파일 이름에는 공백이 없으므로 Dispatch_20180521124202.pdf 입니다.

날짜는 20180521이고 나머지는 메시지 ID인 것 같지만 필요하지 않습니다. 날짜만요.

bash 스크립트(ubuntu 18.04 상자)를 사용한 이 시도는 결국 파일이 있는 디렉터리보다 한 수준 위에 있는 2018-05-21이라는 폴더를 생성하고 모든 PDF 파일을 이 폴더에 저장했습니다.

    for x in /home/tb/temp/*.pdf
do
    d=$(date -r "$x" +%Y-%m-%d)
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

어쨌든 이것은 "e"라는 폴더에 생겼습니다.

for x in /home/tb/temp/*.pdf
do
    d="${x:4:4}-${x:8:2}-${x:10:2}"
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

이 시도는? 결국 각 PDF에 대한 폴더를 만들었습니다.

/home/tb/20180521124202.pdf/Dispatch Fax_20180521124202.pdf /home/tb/20180521121901.pdf/Dispatch Fax_20180521121901.pdf

for x in /home/tb/temp/*.pdf
do
    d=$(echo "$x" | awk -F _ '{print $2}')
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

이전 게시물의 스크립트여기그리고여기이것들은 그들에게 효과가 있었지만 목표는 같았지만 나에게는 같은 행운이 없었습니다.

내 목표는 결국 rsync에서 임시 디렉터리를 채운 다음(다른 서버에서 이 파일을 가져옴) cron을 통해 이 스크립트를 실행하여 날짜를 기준으로 콘텐츠를 폴더로 이동하고 디렉터리를 활성화한 "옵션 + 인덱싱"을 사용하여 Apache를 통해 제공하는 것입니다. . 이 페이지는 인트라넷 전용 페이지이며 이 특정 컴퓨터에서 외부적으로 액세스할 수 없습니다. 디렉토리 구조는 간단합니다. 최종 결과는 YYYY/MM/DD 형식을 따르는 /var/www/html/2018/5/21 등과 유사합니다.

나는 그것을 작동시키는 방법을 모르고 bash 스크립팅에 대한 지식이 매우 녹슬었습니다. 나는 다음과 같은 몇 가지 다른 예를 보았습니다.이것그런데 파일 이름에 공백이 있는 파일에서는 작동하지 않는다는 것을 알게 되었습니다.

나는 아이디어에 열려있습니다!

답변1

귀하의 질문이 제게 완전히 명확하지는 않지만 제 생각에는가능한당신이하고 싶은 일을 이해하십시오.

이것은 당신이 사용하고 있는 루프입니다:

for x in /home/tb/temp/*.pdf
do
    d="${x:4:4}-${x:8:2}-${x:10:2}"
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

귀하가 제공한 예제 파일 이름은 다음과 같습니다.

  1. Dispatch Fax_20180521121901.pdf
  2. Dispatch_20180521124202.pdf

저에게 눈에 띄는 문제 중 하나는 매개변수 대체 표현식( d="${x:4:4}-${x:8:2}-${x:10:2}")이 올바른 결과를 생성하지 않는 것 같습니다. 예를 들면 다음과 같습니다.

> x='Dispatch Fax_20180521121901.pdf'
> d="${x:4:4}-${x:8:2}-${x:10:2}"
> echo ${d}
atch- F-ax

> x='Dispatch_20180521124202.pdf'
> d="${x:4:4}-${x:8:2}-${x:10:2}"
> echo ${d}
atch-_2-01

grep대신 다음과 같이 사용해 볼 수 있습니다 .

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> echo ${d}
20180521

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> echo ${d}
20180521

또는 하이픈을 추가하려는 경우 다음 sed명령 기반 대체를 사용할 수 있습니다.

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
> echo ${d}
2018-05-21

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
> echo ${d}
2018-05-21

이것이 원하는 결과라고 가정하면(예: 형식의 하위 디렉터리가 필요함 %Y-%m-%d) 매개변수 대체 표현식을 grep- 기반 명령 대체로 바꿀 수 있습니다. 그러면 다음과 같은 수정된 루프가 제공됩니다.

for filename in /home/tb/temp/*.pdf; do
    datestring=$(echo "${filename}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
    mkdir -p "${datestring}"
    mv -i -- "${filename}" "${datestring}/"
done

이렇게 하면 양식의 하위 디렉터리가 생성되고 %Y-%m-%d적절한 파일로 채워집니다.


고쳐 쓰다:귀하의 의견에 따르면 귀하가 원하는 것은 form 의 중첩된 하위 디렉터리인 것 같습니다 %Y/%m/%d. 이렇게 하려면 연도, 월, 일 문자열을 별도로 추출해야 합니다. 예를 들면 다음과 같습니다.

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> year=${d:0:4}
> month=${d:4:2}
> day=${d:6:2}
> echo "${year}/${month}/${day}/"
2018/05/21/

이로 인해 다음 루프가 발생합니다.

for filename in /home/tb/temp/*.pdf; do
    datestring=$(echo "${filename}" | grep -Po '\d{8}')
    year=${datestring:0:4}
    month=${datestring:4:2}
    day=${datestring:6:2}
    directory="${year}/${month}/${day}/"
    mkdir -p "${directory}"
    mv -i -- "${filename}" "${directory}"
done

답변2

적극적으로 적대적인 파일 이름을 처리할 필요가 없다면,

sed -E 's/([0-9]{0,7}[^0-9]+)*([0-9]{8}).*/mkdir -p \2; mv "&" \2/e'
#         111111111111111111 2222222222 

패턴은 0~7자리 숫자이고 그 뒤에는 숫자가 아닌 숫자가 여러 번 나오고 그 뒤에 8자리 숫자가 한 번 나옵니다. 두 번째 패턴은 날짜와 일치하는 8자리 숫자입니다.

GNU sed가 없으면 e결과를 플래그 대신 셸로 파이프할 수 있습니다.

관련 정보