echo
절대 경로와 상대 경로를 사용하는 실행하려는 명령(!)이 있습니다 .
이 두 가지 인수를 어떻게 얻습니까?
시도:
d=/tmp/foo;
find "$d" -type f -exec bash -c 'echo d=${1:${#d}} 1="${1%/*}"' bash {} \;
(저는 재귀적이고, 파일로 제한할 수 있고, 파일 이름으로 필터링할 수 있고, 과도한 쉘을 생성하지 않기 때문에 GNU find를 좋아합니다.)
기대:
mkdir -p /tmp/foo/bar/can/haz; touch /tmp/foo/bar/can/haz/bzr.txt
# cmd is run, output is:
d=bar/can/haz 1=/tmp/foo/bar/can/haz
답변1
내보내기를 수행 d
하면 인라인 스크립트에서 사용할 수 있습니다 bash
. bash
여기서도 전혀 필요하지 않습니다 . 당신의 (희망적으로 더 얇고/더 빠른) 것도 sh
그렇게 할 것입니다. 또한 파일당 하나의 셸을 실행할 필요가 없습니다. 변형 을 사용하면 더 많은 파일을 인라인 스크립트에 전달할 수 있습니다 -exec cmd {} +
.
d=/tmp/foo
export d
find "$d" -type f -exec sh -c '
for file do
relative=${file#"$d/"}
dir=${file%/*}
relative_dir=${relative%/*}
relative_dir=${relative_dir:-.}
printf "%10s: %s\n" full "$file" \
relative "$relative" \
dir "$dir" \
reldir "$relative_dir"
done' sh {} +
다음을 제공합니다.
full: /tmp/foo/bar/can/haz/bzr.txt
relative: bar/can/haz/bzr.txt
dir: /tmp/foo/bar/can/haz
reldir: bar/can/haz
그러나 상대 경로만 필요한 경우 다음을 수행하는 것이 더 간단할 수 있습니다.
(cd -P -- "$d" && find . -exec sh -c 'for file do...' sh {} +)
또한 에 전달된 명령 인수가 더 짧아지므로 에 더 많은 인수를 전달할 sh
수 있습니다 .find
sh
귀하의 명령이나 내 명령에는 GNU와 관련된 것이 없습니다 find
. 이는 find
GNU 구현뿐 아니라 모든 POSIX 호환 구현에서 작동합니다 . 귀하의 질문에서 POSIX가 아닌 유일한 부분은 POSIX가 아닌 Korn 쉘 연산자인 연산자 bash
였습니다 .${1:offset}
sh
파일 유형을 지정할 수 있는 재귀적 파일 조회에 대해서는 다음도 참조하세요 zsh
.
(cd -P -- "$d" &&
for file (**/*(ND.)) {
dir=$file:h
printf '%10s: %s\n' relative $file reldir $dir
})
위의 는 의 (일반 파일만 .
해당)과 동일 하며, 은 숨겨진 항목도 포함합니다 .find
-type f
D
find
참고로 일반적인 경우는 다음과 같습니다.
c=$a$b; d=${c:${#a}}
[ "$b" = "$d" ] && echo yes
"yes" 출력이 보장되지는 않습니다 ${#var}
.${var:offset}
연산자는 다음과 같이 작동하므로문자, 아니다바이트.
예를 들어 UTF-8 로케일에서는 a
및 다음 값을 사용하면 yes가 출력되지 않습니다 b
.
a=$'St\xc3' b=$'\xa9phane'
이를 사용하면 $c
내 이름( Stéphane
) 이 해당 문자 $a
의 절반을 포함하고 나머지 절반은 (2자 및 1바이트가 유효한 문자를 형성하지 않지만 여전히 계산됨)이 됩니다 .é
$b
${#a}
3
그렇지 않을 $d
것입니다 .phane
$'\xa9phane'
하지만 특정 경우에는 시스템 로케일에서 일반적으로 사용 가능한 문자 세트 중 인코딩을 포함하는 d=$a/$b
문자 이외의 문자가 없기 때문에 괜찮습니다 ./
/