GNU 찾기: -exec에서 절대 및 상대 경로를 얻습니다.

GNU 찾기: -exec에서 절대 및 상대 경로를 얻습니다.

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수 있습니다 .findsh

귀하의 명령이나 내 명령에는 GNU와 관련된 것이 없습니다 find. 이는 findGNU 구현뿐 아니라 모든 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 fDfind


참고로 일반적인 경우는 다음과 같습니다.

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문자 이외의 문자가 없기 때문에 괜찮습니다 .//

관련 정보