다음 JPEG 파일이 있습니다.
$ ls -l
-rw-r--r-- 1 user group 384065 janv. 21 12:10 CamScanner 01-10-2022 14.54.jpg
-rw-r--r-- 1 user group 200892 janv. 10 14:55 CamScanner 01-10-2022 14.55.jpg
-rw-r--r-- 1 user group 283821 janv. 21 12:10 CamScanner 01-10-2022 14.56.jpg
$ img2pdf
각 이미지를 PDF 파일로 변환하는 데 사용합니다 . 이 작업을 수행할 수 있어야 합니다.
$ find . -type f -name "*.jpg" -exec img2pdf "{}" --output $(basename {} .jpg).pdf \;
결과:
$ ls -l *.pdf
-rw-r--r-- 1 user group 385060 janv. 21 13:06 CamScanner 01-10-2022 14.54.jpg.pdf
-rw-r--r-- 1 user group 201887 janv. 21 13:06 CamScanner 01-10-2022 14.55.jpg.pdf
-rw-r--r-- 1 user group 284816 janv. 21 13:06 CamScanner 01-10-2022 14.56.jpg.pdf
.jpg
PDF 파일 이름의 일부를 제거하는 방법은 무엇입니까 ? 즉, 나는 그것을 원하고 CamScanner 01-10-2022 14.54.pdf
원하지 않는다 CamScanner 01-10-2022 14.54.jpg.pdf
.
단독으로 사용하면 $ basename filename .extension
확장자 없이 파일 이름을 인쇄합니다. 예:
$ basename CamScanner\ 01-10-2022\ 14.54.jpg .jpg
CamScanner 01-10-2022 14.54
$ find
하지만 내 명령에서 구문이 작동하지 않는 것 같습니다. 이유를 아시나요?
참고: 이 부품은 동일한 부품 $ img2pdf
으로 교체해도 제거되지 않습니다 .$ echo
$ basename
.jpg
$ find . -type f -name "*.jpg" -exec echo $(basename {} .jpg).pdf \;
./CamScanner 01-10-2022 14.56.jpg.pdf
./CamScanner 01-10-2022 14.55.jpg.pdf
./CamScanner 01-10-2022 14.54.jpg.pdf
답변1
명령의 문제점 find
은 주변 명령 대체가 basename
쉘에 의해 수행된다는 것입니다앞으로심지어 실행이 시작됩니다 find
( find
매개변수가 무엇인지 평가하는 단계로).
선택적 인수가 있는 간단한 유틸리티 이외의 다른 것을 실행해야 할 때마다 find
(예를 들어 질문에서와 같이 파이프, 리디렉션 또는 확장을 수행해야 하는 경우) 다음 작업을 수행하려면 셸을 사용해야 합니다.
find . -type f -name '*.jpg' \
-exec sh -c 'img2pdf --output "$(basename "$1" .jpg).pdf" "$1"' sh {} \;
또는 더 효율적으로(각 호출은 sh -c
발견된 경로 이름 일괄 처리)
find . -type f -name '*.jpg' -exec sh -c '
for pathname do
img2pdf --output "$(basename "$pathname" .jpg).pdf" "$pathname"
done' sh {} +
또는 zsh
,
for pathname in ./**/*.jpg(.DN); do
img2pdf --output $pathname:t:r.png $pathname
done
이는 globbing 한정자를 사용하여 .DN
일반 파일만 일치시키고( .
) 숨겨진 이름 일치를 허용하며( D
) 일치하는 항목이 없으면 패턴을 제거합니다( N
). 그런 다음 :t
수정자를 사용하여 "tail"(파일 이름 구성 요소)을 추출 $pathname
하고 :r
결과 기본 이름(파일 이름 접미사 없음)의 "루트"를 추출한 다음 이를 .png
끝에 추가합니다.
위의 모든 변경사항은 다음과 같습니다.현재 디렉터리에 출력 쓰기, JPEG 파일이 있는 곳이면 어디든 가능합니다. 모든 JPEG 파일이 현재 디렉토리에 있는 경우 이는 전혀 필요하지 않으며 find
와일드카드 패턴 확장 시 간단한 루프를 사용할 수 있습니다 *.jpg
.
for pathname in ./*.jpg; do
img2pdf --output "${pathname%.jpg}.png" "$pathname"
done
매개변수 대체는 ${pathname%.jpg}
값 끝에서 제거됩니다. 이 대체품을 사용하고 싶을 수도 있습니다.jpg
$pathname
바꾸다 basename
JPEG 파일이 발견된 원래 디렉터리에 출력을 쓰려는 경우( find
예: 다음과 같은 여러 디렉터리를 사용하는 경우)
find . -type f -name '*.jpg' -exec sh -c '
for pathname do
img2pdf --output "${pathname%.jpg}.pdf" "$pathname"
done' sh {} +
또한보십시오:
답변2
실용적인 관점에서 질문 끝에 설명된 상태에 도달하면 다음과 같습니다.
./CamScanner 01-10-2022 14.56.jpg.pdf
./CamScanner 01-10-2022 14.55.jpg.pdf
./CamScanner 01-10-2022 14.54.jpg.pdf
rename
선택적으로 다음을 사용하여 원하는 최종 파일 이름을 얻을 수 있습니다 .
~ rename 's/jpg.pdf/pdf/'
답변3
@Ulrich Schwarz의 의견이 정확합니다. 완료하려면 따옴표나 작은따옴표로 묶인 파일 이름이 없다고 가정해 보겠습니다.
.jpg 없이 기본 이름만 출력하도록 구문을 조정한 다음, find
적절한 경우 확장자를 사용하여 구문을 awk
다시 작성합니다 img2pdf
..jpg
.pdf
이 find
명령은 기본 이름만 출력합니다.
$ find . -type f -name "*.jpg" -exec basename {} .jpg \;
CamScanner 01-10-2022 14.56
CamScanner 01-10-2022 14.55
CamScanner 01-10-2022 14.54
이제 이러한 기본 이름을 전달 awk
하고 awk가 올바른 구문을 구성하도록 합니다 img2pdf
.
$ find . -type f -name "*.jpg" -exec basename {} .jpg \; | \
awk '{print "cp -vp '\''" $0 ".jpg'\'' --output '\''" $0 ".pdf'\''"}'
img2pdf 'CamScanner 01-10-2022 14.56.jpg' --output 'CamScanner 01-10-2022 14.56.pdf'
img2pdf 'CamScanner 01-10-2022 14.55.jpg' --output 'CamScanner 01-10-2022 14.55.pdf'
img2pdf 'CamScanner 01-10-2022 14.54.jpg' --output 'CamScanner 01-10-2022 14.54.pdf'
구문이 괜찮아 보이면 즐겨 사용하는 셸에 파이프하세요.