$(echo "cd ..") 명령을 찾을 수 없습니다.

$(echo "cd ..") 명령을 찾을 수 없습니다.

좋아요 -bash: cd ..: command not found.

지정된 디렉터리를 반복하는 스크립트를 작성했습니다. 항상 효과가 있었지만 지금은 무엇이 바뀌었는지 모르겠습니다.

$ type up
up is a function
up () 
{ 
    local arg="$@";
    if [ -z "$arg" ]; then
        cd ..;
        return 1;
    fi;
    local arr=();
    local sep='/';
    local IFS="$sep";
    local DIRS;
    read -ra DIRS <<< "$(pwd)";
    for ((i=${#DIRS[@]}-1; i>=0; i-- ))
    do
        if [ "${DIRS[i]}" = "$arg" ]; then
            local first=${arr[0]};
            arr=("${arr[@]:1}");
            $(printf "%s" "cd $first" "${arr[@]/#/$sep}" && echo "/");
            return 1;
        else
            arr+=('..');
        fi;
    done;
    echo "Directory \"$arg\" could not be found in path. Check spelling and try again." 1>&2;
    return 0
}

속도

  1. 매개변수가 전달되지 않으면 이전 디렉터리로 이동합니다.
  2. 매개변수가 전달되는 경우:
    1. 잡아서 pwd분리해/

    2. 대기열 뒤에서 오는 디렉터리 목록을 반복합니다.

    3. 현재 디렉터리가 매개변수와 일치하지 않으면 ..목록에 추가하세요.

    4. dir이 명령줄 arg와 일치하는 경우 ..로 구분된 압축을 풀고 /문자열을 명령으로 실행합니다.

      printf "%s" "cd $first" "${arr[@]/#/$sep}" && echo "/"
      
      # printf "%s" "cd $first" :   prints 'cd ..' (command & the first placeholder) 
      # "${arr[@]/#/$sep}"      :   prints the remaining '..' joined by '/'
      # echo "/"                :   adds a trailing '/' to the relative path 
      #                               which could have been included in the 
      #                               previous step but separated for comprehension
      
      # Given, pwd = /Users/dev/workspace/project/foo
      # `up workspace` navigates to 'cd ../../'
      

디버깅(터미널에서)

> cd ..
# works as expected

> $(echo "cd ..")
# works as expected --> maybe something with the "/" is breaking it?

> $('cd ..')
# -bash: cd ..: command not found

> $('cd ../')
# -bash: cd ../: No such file or directory

> which cd
# /usr/bin/cd

> echo $PATH
# /usr/bin

> type cd
# cd is a shell builtin

> alias cd
# -bash: alias: cd: not found

> shopt expand_aliases
# expand_aliases    on

OSX의 bash3.2에서는 대부분의 환경 변수(예: CDPATH)를 설정 해제하거나 깨끗한 환경(예:)으로 셸을 여는 것이 env -i bash --noprofile --norc도움이 되지 않습니다.

논평

내 bash는 약간 녹슬었으므로 이를 유지 관리할 수 있는 더 나은 방법을 자유롭게 지적해 주십시오. 나는 그것이 아마도 필요하지 않거나 정확하지 않다는 것을 알고 있으며 더 효율적일 수 있지만 따르기가 더 어려운 return일부 구현을 보았습니다 .find

답변1

$(echo "cd ..")쉘 명령 echo "cd .."(예: echo단일 인수가 있는 명령 cd ..)을 실행하고 출력( cd ..)을 얻은 다음 해당 출력을 공백(및 와일드카드, 여기서는 중요하지 않음)으로 분할하고 두 단어의 합계를 얻은 cd다음 인수를 사용 ..합니다 . 이는 단지 쉘 명령을 실행하는 복잡하고 오류가 발생하기 쉬운 방법입니다 .cd..cd ..

와는 별개로여기서 슬래시를 설정하면 IFS단어가 부분으로 분할됩니다.공백으로 나누지 말고 슬래시로 나누세요..

따라서 예를 들어 을 실행하면 $(echo "cd ../..")명령 대체 결과가 로 분할되지 않고 cd, ../..로 분할 됩니다 cd ... 여기에 있는 공백은 이제 쉘 명령줄에 입력하는 ..것처럼 명령 이름의 일부가 됩니다 ."cd .." ..

단어 분리에 의존하지 않고(특히 디렉토리 이름에 공백이 포함된 경우 분리되므로) 명령과 인수를 분리하는 것이 좋습니다. 변수에 디렉토리 이름을 작성하고 사용하십시오. 예:

dir=$(printf "../..")
cd -- "$dir" 

아니면 더 정확하게는

printf -v dir "../.."
cd -- "$dir" 

또한 아마도 거기에 있을 필요도 없을 것입니다 printf. 를 사용 "${arr[*]}"하면 의 첫 번째 문자와 연결된 배열 요소를 가져올 수 있으므로 를 IFS사용하면 IFS=/슬래시로 연결됩니다.

예를 들어:

arr=(.. .. ..)
IFS=/
dir="${arr[*]}"

dir로 설정 ../../...

관련 정보