basename과 함께 find -exec를 사용할 때 디렉토리에 공백을 어떻게 허용합니까?

basename과 함께 find -exec를 사용할 때 디렉토리에 공백을 어떻게 허용합니까?

주어진 경로에서 모든 디렉터리를 찾고 해당 디렉터리 내에서 다른 위치에 있는 동일한 이름을 가진 디렉터리에 대한 소프트 링크를 만들려고 합니다. 많은 디렉토리에는 이름에 공백이 있습니다. 다음 코드를 함께 엮어보니 공백이 없는 한 제대로 작동하는 것 같습니다.

find /some/path/* -maxdepth 0 -exec sh -c "ln -s /some/other/path/"'$(basename {})'" {}" \;

공백을 처리하려면 어떻게 변경해야 합니까? 일반적으로 내 디렉터리 이름에는 이러한 미러 디렉터리가 없지만 이러한 미러 디렉터리는 내 Windows PC에 있으며 그 안에서 공백을 사용합니다. 어떤 도움이라도 대단히 감사하겠습니다!

편집하다

cuonglm과 Gilles의 주장에 대한 답변:

  • 명령 인수의 순서에는 아무런 문제가 없지만 ln -s설명에서 내가 원하는 것이 무엇인지 명확하지 않습니다. 각 디렉토리에 대해 /some/path/심볼릭 링크를 만들고 싶습니다존재하다이 디렉토리는 에서 동일한 이름의 디렉토리를 가리킵니다 /some/other/path/. /some/other/path/그렇습니다 .source/some/path/destination내가 이렇게 하고 싶은 이유는 /some/path/include에 디렉터리의 하위 집합이 있고 /some/other/path/각 디렉터리의 하위 집합에서 전체 집합으로의 링크를 원하기 때문입니다.

  • 경로에 디렉토리가 너무 많지는 않겠지만 이를 막지 않는 것은 무의미한 결함이라는 데 동의합니다.

  • 사용하지 않은 이유 -type d는 주어진 경로에 디렉터리만 있고 파일은 없기 때문인데, 포함시키는 것이 더 낫다는 것을 깨달았습니다.

답변1

명령에 몇 가지 문제가 있습니다.

  • /some/path/*아래 디렉터리가 너무 많으면 매개변수 목록이 너무 깁니다. 오류가 발생할 수 있습니다./some/path

  • 디렉터리나 파일을 필터링하지 않습니다.

  • 인라인 스크립트를 사용하기 때문에 매우 비효율적이지만 sh -c,-exec ... {} \;

  • ln매개변수 위치가 잘못 되면 ln -s source destto 대신 to to로 심볼릭 링크가 생성됩니다.sourcedestdestsource


POSIX 방식으로 이 작업을 수행할 수 있습니다.

find /some/path ! -path /some/path -prune -type d -exec sh -c '
  for f do
    ln -s "$f" /some/other/path/"${f##*/}"
  done
' sh {} +

또는 귀하가 find지원하는 경우 -maxdepth:

find /some/path -maxdepth 1 -type d -exec sh -c '...' sh {} +

답변2

첫째, 항상 {}에서 별도의 매개변수로 사용됩니다 find -exec …. 일부(전체는 아님) 버전에서 작동하는 버전을 사용하세요. 하지만 공백 등과 같은 "비정상적인" 문자가 포함된 파일 이름을 처리하는 것은 불가능합니다. (정확히 어떤 문자가 문제를 일으키는지는 사용 중인 특정 위치에 따라 다릅니다.) 별도의 매개변수로 전달됩니다. 그 다음의 첫 번째 매개변수는 입니다.stuff{}morestufffind'"{}{}sh -c CODE$0변수 확장에 대한 큰따옴표를 잊지 마세요..

find … -exec sh -c 'ln -s /some/other/path/$(basename "$0") "$0"' {} \;

(전체적으로 작은따옴표를 사용하여 인용을 단순화했습니다.)

명령에 하나 이상의 문제가 있습니다. find심볼릭 링크가 이미 존재하는 반환된 위치에 심볼릭 링크를 생성하려고 합니다 . 아래에 심볼릭 링크를 만들려는 것 같습니다 /some/other/path. 이 경우 매개변수를 바꿔야 합니다 ln(예: 및 mv, cp기존 파일 먼저, 대상 마지막).

find /some/path/* -maxdepth 0 -exec sh -c 'ln -s "$0" /some/other/path/$(basename "$0")' {} \; 

basenamesh대신 셸 문자열 조작 구조를 사용하고 호출을 한 번에 일괄 처리하면 작업 속도를 높일 수 있습니다 .

find /some/path/* -maxdepth 0 -exec sh -c '
  for x do
    ln -s "$x" /some/other/path/${x##*/};
  done' {} +

이것이 실제 find명령 이라면 find여기서는 쓸모가 없습니다. 요점은 find하위 디렉터리로 재귀하는 것입니다. 비재귀적 조회는 때때로 필터를 활용하는 데 유용합니다(예: 특정 유형의 파일 또는 특정 기간 내에 수정된 파일에 대해서만 작동). 그러나 find필터링 없는 비재귀는 의미가 없습니다.

for x in /some/path/*; do
  ln -s "$x" "/some/other/path/${x##*/}";
done' {} +

또는

cd /some/path
for x in *; do
  ln -s "$PWD/$x" "/some/other/path/$x";
done' {} +

아니면다루기 힘든:

autoload -U zmv
alias zln='zmv -L'
zln -s '/some/path/*' '/some/other/path/$f:t'

관련 정보