$(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 ..)を取得し、その出力を空白(およびワイルドカード、ここでは重要ではありません)に分割し、2つの単語の合計を取得して引数を使用し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に設定../../..

関連情報