`find`를 사용하여 해당 파일의 디렉토리로 이동하는 방법


11

파일을 찾은 다음 파일이 들어있는 디렉토리를 입력하고 싶습니다. 시도 find /media/storage -name "Fedora" | xargs cd했지만 물론 is not a directory오류가 발생했습니다.

한 줄 명령으로 부모 디렉토리를 어떻게 입력합니까?


1
여러 위치에서 여러 파일이있는 경우 어떻게해야합니까?
Sergiy Kolodyazhnyy 2012 년

@Serg Fedora * .iso 파일을 검색하는데 하나만 있다는 것을 알고 있습니다. 하나 이상이 있다면 첫 번째 이분법에 들어갔을 것입니다.
Hrvoje T

bash with shopt -s globstar에서는 할 수 cd /media/storage/**/Fedora는 있지만 첫 번째 일치에서 glob 평가를 중단하지는 않습니다 (강철 드라이버의 솔루션보다 느립니다. 대화 형 사용의 경우 일반적으로 마우스에 도달하고 디렉토리 이름을 복사 / 붙여 넣는 것입니다. (그리고 내가 원하지 않는 후행 경로 구성 요소를 제거하는 데 필요한 alt + backspace),이 작업을 많이 수행하면 쉘 기능을 만들 가치가 있다고 생각합니다.
Peter Cordes

1
BTW, xargs cd작동하지 않을 수 있습니다. cd쉘 자체의 컨텍스트를 수정해야하기 때문에 쉘 내장으로 만 작동 할 수 있습니다. xargs자식 프로세스가 그렇게 할 수있는 방법은 없습니다 . 이것이 "물론"이라는 의미이거나, find인쇄 경로 에 공백이 포함되어 -d \n있거나 사용하지 않았 거나 xargs로 분할 된 공백이있는 경우 IDK 입니다. 또는 find -exec {} \;.
Peter Cordes

참고 : 당신은 그런 식으로 실행할 수 없습니다 cd. cdbash는 내장 된 bash입니다 cd. 별도의 명령 인 경우 dir을 변경 한 다음 종료합니다 (이전에는 dir을 변경하지 않고 이전과 동일한 상태 인 쉘로 돌아갑니다).
ctrl-alt-delor

답변:


14

적어도 GNU가 있다면 디렉토리를 얻는 데 find사용할 수 있습니다.-printf '%h'

       %h     Leading directories of file's name (all but the last ele‐
              ment).  If the file name contains no slashes (since it is
              in  the  current  directory)  the %h specifier expands to
              ".".

그래서 당신은 아마 할 수

cd "$(find /media/storage -name "Fedora" -printf '%h' -quit)"

-quit여러 인수를 방지해야 cd하나 개 이상의 파일이 일치하는 경우이다.


1
-quit반드시 지원되는 것은 아닙니다. NetBSD에서라는 이름 -exitunix.stackexchange.com/a/62883/117599
phk

2
printf가 없다면 -exec dirname을 대신 할 수 있습니까?
Guy

@Guy 좋은 생각 예 그것은 그것이 작동하는 것처럼 들린다
steeldriver

6

steeldriver의 솔루션과 유사 하지만 다음 과 함께 (GNU 또는 FreeBSD와 같이 지원하는 -execdir경우 ) 사용 :findfindpwd

cd "$(find /media/storage -name "Fedora" -execdir pwd \; -quit)"

-quit단일 결과 만 있고 전체 디렉토리를 크롤링하는 데 문제가없는 경우에만 선택 사항입니다. NetBSD -exit와 OpenBSD에는 존재하지 않습니다.


그리고 무엇 \;입니까?
Hrvoje T

1
@HrvojeT 마찬가지로 명령 실행을위한 매개 변수의 끝을 -exec알려줍니다 find. 그러나 pwd여기서는 매개 변수없이 호출하고 싶기 때문에 \;바로 뒤에 넣 습니다.
phk

어떤 있습니까 find구현을 지원하는 execdir하지만 -printf %h? 나에게는 없을 것 같습니다. 불행히도 POSIX에는 아무도 필요하지 않습니다 : /
Peter Cordes

1
@PeterCordes FreeBSD 's find: freebsd.org/cgi/man.cgi?find%281%29 (FreeBSD 11 설치에서 확인했습니다.)
phk

@PeterCordes NetBSD ( netbsd.gw.com/cgi-bin/man-cgi?find++NetBSD-current ) 및 OpenBSD ( man.openbsd.org/OpenBSD-current/man1/find.1 ) 와 동일합니다 . 후자는 -quit/ 전혀 지원하지 않습니다 -exit.
phk

5

찾은 디렉토리에서 find를 새 쉘로 실행할 수 있습니다.

exec find /media/storage -name "Fedora" -execdir "$SHELL" \;

그 후 현재 디렉토리는 Fedora라는 파일을 가진 디렉토리가됩니다. ;)

분명히 이것은 대화식으로 명령을 입력하는 경우 원하는 것과 유사합니다.


4

zsh:

cd /media/storage/**/Fedora([1]:h)

cd라는 파일이 들어있는 첫 번째 (알파벳 순서) 디렉토리에 Fedora.

  • **: 모든 수준의 디렉토리 (숨겨진 디렉토리는 기본적으로 생략됩니다. Dglob 한정자를 사용하여 포함하십시오)
  • [1]: 첫 번째 만
  • :h: 헤드 수정 자 : dirname을 사용하십시오.

반대로 cd "$(find ...)"디렉토리 이름이 개행 문자로 끝나는 경우에도 작동합니다. 또 다른 장점은 일치하는 디렉토리가 없을 때 일치하지 않는 오류 메시지가 표시 된다는 것입니다 (대부분의 쉘 cd ""에서는 자동으로 아무것도 수행하지 않습니다).

단점은 /media/storage돌아 오기 전에 전체를 크롤링한다는 것입니다 .


bash에서 cd여러 인수가있는 경우 어쨌든 첫 번째 인수 만 보이므로 경로에 공백이 없으면 cd $(dirname /media/storage/**/Fedora)(와 함께 shopt -s globstar) 작동 합니다. 올바르게 인용하려면 bash 배열이 가장 쉽다고 생각합니다 target=(/media/storage/**/Fedora); cd "${target%/*}". 그러나 그 시점에서 마우스를 사용하여 찾기 출력을 대화식으로 표시하지 않고 복사 / 붙여 넣기하는 것이 더 빠를 것입니다.
Peter Cordes

2
@ PeterCordes에서 많은 dirname구현은 하나 이상의 인수를 허용하지 않습니다. 공백 이 아니며 현재 $IFS기본적으로 공백, 탭 및 줄 바꿈 문자 및 와일드 카드 문자입니다. 인지주의 bash의는 cd하나 개 이상의 인수를 받아들이는가 (컴파일 된 방법에 따라 달라집니다 CD_COMPLAINS에서 config-top.h). 장래의 버전 bash도 결국 zsh에서와 같이 두 개의 arg 기능을 구현할 것이라고 상상할 수 있습니다 .
Stéphane Chazelas

감사. 방금 GNU coreutils dirname 맨 페이지를 보았습니다. dirname 버전은 어쨌든 끔찍합니다. 나는 그것이 효과가있는 경우 대화 형으로 시도 할 수있는 것으로 언급했습니다. 내 배열 기반 버전은 "${target%*/}"첫 번째 배열 요소 ( /Fedora스트립 제거) 로만 확장 되므로 이러한 문제로 고통받지 않습니다 . 버전이 경로 이름의 가능한 모든 문자에 대해 완전히 견고하다고 생각합니다.
Peter Cordes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.