해결됨: 댓글의 업데이트를 참조하세요.
파일 이름에 날짜가 포함된 파일을 해당 날짜를 기준으로 폴더로 정렬하려고 합니다. 이러한 파일은 아래와 같이 파일 이름에 공백이 있었습니다. 오래된 파일도 있어서 정리해야 합니다.
일정 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
귀하가 제공한 예제 파일 이름은 다음과 같습니다.
Dispatch Fax_20180521121901.pdf
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
결과를 플래그 대신 셸로 파이프할 수 있습니다.