경로를 매개변수로 받아들이고 경로에 있는 모든 .mkv 파일을 처리하는 스크립트를 작성 중입니다. 경로는 절대 경로, 상대 경로 또는 단일 파일일 수 있습니다. 그러나 반복되는 파일의 절대 경로가 여전히 필요합니다.
지금까지 내가 한 일은 다음과 같습니다.
#!/bin/bash
path=$1
if ! [ -e "$path" ]; then
path=$(pwd)
fi
find "$path" -type f -name '*.mkv' | sort | xargs realpath | while read file; do
echo "Processing $file"
done
이는 경로 및/또는 파일에 공백이 없을 때 작동하지만 공백으로 인해 실패합니다.
올바른 접근 방식은 무엇입니까?
답변1
그리고 zsh
:
#! /bin/zsh -
for file (${${1-.}:P}/**/*.mkv(ND.))
print -r processing $file
${1-.}
Bourne 쉘에서와 같이.
if$1
is not set로 확장됩니다(if$#
== 0; if가 나쁜 인터페이스이고,$1
is가 존재하지 않는 파일인 경우는 아닙니다. 이는 사용자에게 큰 놀라움이 될 것입니다).${param:P}
realpath()
해당 확장 으로 확장됩니다 .**/
심볼릭 링크를 따르지 않고.
한정자는 선택만 하므로 모든 파일에 대해 동일한 작업을 수행할 필요가 없습니다.정기적인파일이므로 심볼릭 링크가 아닙니다.**/
모든 수준의 하위 디렉터리와 일치N
nullglob,D
dotglob.
에 대한 Glob 한정자정기적인오직.
답변2
모든 파일 대신 경로 자체를 전처리할 수 있습니다.
find "$(realpath -- "$path")" -type f -name '*.mkv' -exec printf 'Processing %s\n' {} +
printf
실제로 파일로 수행하려는 작업으로 바꾸십시오 . +
호출당 여러 파일을 처리할 수 있음을 나타냅니다. 그렇지 않은 경우 대신 를 사용하세요 \;
.
답변3
Stephen의 의견에 동의합니다. 항상 -exec
출력 후 처리를 선호합니다 find
. 꼭 필요한 경우 항상 -print0
명시적인 파일 이름 구분을 허용하는 도구를 사용하십시오. 입력의 파일 이름을 사용하는 대부분의 도구는 일종의 --null
, --zero
/ -z
또는 -0
플래그를 지원하여 입력을 0바이트 구분으로 해석하도록 합니다.
귀하의 경우에는 아마도 zsh를 선호할 것입니다. 그러나 bash를 고수하고 싶다고 가정하면 아무런 문제 없이 동일한 작업을 수행할 수 있습니다. sort
어쨌든 와일드카드는 알파벳순으로 정렬되므로 생략해도 됩니다 . bash는 재귀적 글로빙을 수행할 수 있으므로 생략할 수 있습니다 find
(zsh는 글로빙할 때 파일 유형을 제한할 수도 있고 bash에서는 실제로 파일성을 테스트해야 함 ). 어쨌든 파일을 처리하기 때문에 -f
생략할 수 있습니다 . xargs
:
#!/bin/bash
# Fail when something goes wrong!
set -e
# enable recursive globs, and don't fail when there's nothing there
shopt -s globstar
shopt -s dotglob
shopt -s nullglob
inpath="$1"
if ! [ -e "${inpath}" ]; then
inpath="$(pwd)"
fi
for file in "${inpath}/**/*.mkv"; do
# check whether regular file, skip if not
[ -f "${file}" ] || continue
fullpath="$(realpath -- "${file}")"
echo "Processing ${fullpath}" # Could / might prefer to use printf here instead
done
너할 수 있는기본 정렬이 실제로 필요한 것이 아닐 경우를 대비해 항목을 다르게 정렬하세요. 교체해야 해
for file in "${inpath}/**/*.mkv"; do
비슷한 것
unsorted=( ${inpath}/**/*.mkv )
readarray -d '' -t sorted_files < \
<(printf '%s\0' "${unsorted[@]}" \
| sort -z --whateveroptions \
)
for file in "${sorted_files[@]}" ; do
readarray
전달된 문자열에 구분 기호를 설정하는 옵션이 있습니다 -d
. 빈 문자열을 전달하면 0바이트가 구분 기호로 사용됩니다. readarray
트림 -t
(여기서는 필요하지 않지만 안전한 기본값인 것으로 확인됨)은 sort -z
0바이트를 구분 기호로 사용합니다. "${arrayname[@]}"
이 배열의 반복 가능한 요소 목록으로 확장되지만 요소에 공백과 줄 바꿈이 포함되어 있어도 안전하게 사용할 수 있습니다.
zsh에서는 와일드카드로 찾은 파일을 정렬할 수도 있습니다. 가능할 때마다 zsh를 사용하십시오.