가장 가까운 일치 폴더 찾기

가장 가까운 일치 폴더 찾기

"/" 발생 횟수를 기준으로 결과를 정렬 $ find . -name scripts -type d한 다음 첫 번째 결과를 선택하는 가장 좋은 방법은 무엇입니까?

cd내 프로젝트의 공용 폴더를 가리키는 함수를 만들고 싶습니다 . 나는 그것이 당신의 상대 디렉토리에 기초하여 유연해지기를 원합니다.

따라서 폴더 구조가 모두 비슷한 10개의 프로젝트가 있는 경우:

~/project-a/project/folder/structure
~/project-b/project/folder/structure
~/project-c/project/folder/structure

저 할 수 있어요:

$ cd ~/project-a
$ cdd structure

~/project-a/project/folder/struct에 배치됩니다.

고쳐 쓰다

예를 들어 다음과 같이 예측 가능한 방식으로 결과를 정렬할 수 없습니다.

$ find . -type d -name "themes"

./wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes
./wp-content/plugins/jetpack/modules/infinite-scroll/themes
./wp-content/plugins/smart-youtube/themes
./wp-content/plugins/wptouch-pro/themes
./wp-content/themes
./wp-includes/js/tinymce/themes

cdd함수가 가장 가까운 결과로 내려가기를 원합니다 . 이 예에서는 입니다 ./wp-content/themes.

답변1

이를 통해 zsh다음을 수행할 수 있습니다.

cdd() cd -- **/$1(/Od[1])

cdd themes

cdd기능은 모든 유형의 파일을 찾습니다.목차( /) 에 인수로 제공된 이름을 사용하여 epth별로 정렬 $1하고 첫 번째 항목( )을 선택합니다.Od[1]

D비효율적인 점은 현재 디렉터리에 일치하는 디렉터리가 있더라도 전체 디렉터리 트리를 크롤링한다는 것입니다(숨겨진 디렉터리를 건너뛰고 변경하기 위해 glob 한정자를 추가함).

한 번에 한 수준씩 디렉터리 트리를 탐색하려면 다음을 수행할 수 있습니다.

cdd() {
  local dirs matches
  dirs=(.)
  while (($#dirs)) {
    matches=($^dirs/$1(N/[1]))
    if (($#matches)) {
      cd $matches[1]
      return
    }
    dirs=($^dirs/*(/N))
  }
  print >&2 Not found
  return 1
}

답변2

별칭은 중간에 매개 변수를 허용할 수 없고 끝에서만 허용하므로 이 문제를 해결하기 위해 및 별칭을 사용할 수 없습니다. 이를 달성하려면 기능이 필요합니다.

다음 기능이 귀하의 요구 사항을 충족할 수 있습니다.

cdd() { 
   cd `find . -type d -name "$1"|head -n1`
}

로그인할 때 이 줄이 한 번 실행되도록 .profile(또는 .bashrc 파일)에 이 줄을 추가해야 합니다.

테스트를 위해 이를 이라는 파일에 넣은 다음 func.sh가져오면(즉, "." 연산자를 사용하여 실행) 환경의 일부가 됩니다.

. ./func.sh

참고: 파일을 변경한 경우 func.sh해당 파일을 다시 가져와야 합니다.

그런 다음 다음과 같이 사용할 수 있습니다.

cdd <dirname>

이제 함수는 <dirname>현재 경로와 그 이름을 가진 디렉터리 아래를 검색하고, cd찾은 첫 번째 일치 항목( head -n1)을 검색합니다.

find처음에 원하는 결과를 얻기 위해 작업을 세부적으로 조정할 수 있습니다 . 바라보다 man find.

가장 가까운 일치 항목을 찾으려면 find 출력을 정렬하여 가장 짧은 줄을 제공할 수 있습니다.

find . -type d -name "$1"| awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2- | head -n1

(이 awk명령은 다음에서 도난당했습니다.여기.)

이것은 find의 출력에서 ​​가장 짧은 줄을 반환합니다. 그러나 디렉터리를 찾고 있는데 proj다음과 같은 구조가 있으면 잘못된 디렉터리가 반환됩니다.

./d1/d2/d3/proj
./longdirname/proj

또는 결과의 문자 수를 세어 /이 문제를 해결할 수 있습니다.

답변3

find이 bash 기능은 현재 디렉터리의 모든 디렉터리 계층에 대해 무차별 대입 크래킹을 수행하고 지정된 디렉터리를 검색합니다.

cdd() {
  if [ "$#" -ne 1 ]
  then
    printf '%s: Error: one directory name expected\n' "${FUNCNAME[0]}" >&2
    return
  fi

  maxdepth=$(find . -type d -exec sh -c 'printf %s "$1" | LC_ALL=C tr -dc / | wc -c' findshell {} \; | sort -n | tail -1)
  for((i=1; i <= maxdepth; i++))
  do
    dir=$(find . -mindepth "$i" -maxdepth "$i" -type d -name "$1")
    if [ -n "$dir" ]
    then
        command cd -- "$dir"
        return
    fi
  done
  printf '%s: %s: no such directory found\n' "${FUNCNAME[0]}" "$1" >&2
}

첫 번째 find명령은 현재 디렉토리 아래의 각 디렉토리에 대해 쉘 조각을 실행합니다. 쉘 조각은 디렉토리 이름을 tr& wc파이프에 인쇄하여 슬래시가 아닌 모든 문자를 제거한 다음 슬래시 수를 계산합니다. 나는 이 기술을 ilkkachu와 Stéphane Chazelas에게서 배웠습니다.여기. 모든 디렉토리 깊이를 출력한 후 sort | tail가장 큰 숫자를 찾습니다. 이 숫자는 검색해야 하는 최대 디렉터리 깊이입니다.

find그 후 현재 디렉터리부터 시작하여 가장 깊은 디렉터리까지 차례로 각 디렉터리의 깊이를 제한하는 루프입니다 . 일치하는 항목이 발견되면 cd함수를 종료합니다. 일치하는 항목이 없으면 루프를 종료하고 stderr에 메시지를 인쇄합니다.

답변4

bash의 재귀 와일드카드 기능을 사용할 수도 있습니다.

shopt -s globstar  # in ~/.bashrc, or just in cdd() {}
cd **/structure/

**확장은 조회와 거의 동일한 순서로 발생하므로 대부분 동일한 문제가 존재한다고 생각합니다 . 하지만 너무 간단하고 유용해서 간과할 수도 있습니다!

여러 매개변수가 있는 bash거부의 최신 버전cd따라서 이는 일치하는 항목이 하나만 있는 경우에만 작동합니다. 그렇지 않으면 당신은 얻을 것이다 cd: too many arguments.

따라서 쉘 기능이 필요합니다. array=( **/"$1"/ )비어 있지 않은 경우 첫 번째 요소가 사용될 수 있지만 함수를 작성하는 경우 find -depth -type d | tail -1마지막 결과(가장 얕은 결과 중 하나)를 얻기를 원할 수도 있습니다. 또는 -maxdepth나무가 상당히 깊을 것 같으면 단계별로 사용하십시오.

관련 정보