up
私があるディレクトリの上の指定されたディレクトリに簡単に移動できるようにする(私のbashrcの関数として)というコマンドがあります。このコマンドはうまく機能しますが、bashタブ補完機能を追加すると、はるかに便利です。現在のパスのディレクトリを識別し、完了のためにリストする完了スクリプトを作成しました。私が経験している問題は、ディレクトリを変更するたびに完了スクリプトが再ロードされないように見えるため、以前のディレクトリにあるかのように結果が表示されることです。コマンド機能をup
追加してコマンドを変更できましたが、exec bash
任意のディレクトリ変更コマンドでこれを実行できるかどうかはわかりません。exec bash
for while the command is running を追加すればこれを行うことができるようですが、cd
これを行う最善の方法が何であるかよくわかりません。
たとえば、
端末を開くと、ホームディレクトリにあります。
~$
これを入力すると、次のような結果up <TAB><TAB>
が表示されます。
~$ up
username home
ここで、ユーザー名はマイコンピュータのユーザー名です。その後、CDを入力して次のようにdir1/dir2/
なりup <TAB><TAB>
ました。
~/dir1/dir2$ up
username home
繰り返しますが、ディレクトリを変更しましたが。
私の完了スクリプトとupスクリプトのコードは次のとおりです。
スクリプトを完成させる:
#/usr/bin/env bash
LS=$(echo $PWD)
LSARRAY=${LS//\// }
complete -W "$LSARRAY" up
先頭へ戻るコマンド(.bashrcから)
LS=$(echo $PWD)
LSARRAY=(${LS//\// })
i=1
if [[ $LS == *$1/* ]]; then
FIND=$1
if [[ $1 == */* ]]; then
ARR=(${FIND//\// })
FIND=${ARR[${#ARR[@]}-1]}
fi
while [ "${LSARRAY[${#LSARRAY[@]}-$i]}" != "$FIND" ] && [ $i != ${#LSARRAY[@]} ]; do
cd ../
i=$(($i+1))
done
exec bash
else
echo "Did not find directory $1"
fi
ベストアンサー1
以下は、次のことを試みる関数up
(プログラミング可能な完了対応を含む)の代替実装です。
- 任意のパスを使用してください(スペースと改行を含む)。
- 変数を変更しないでください
IFS
。これは次の場合に便利です。正しい回復; - いくつかの特別なディレクトリを明示的に処理します(
.
ここでは..
任意の方法で処理されるため、必要に応じてコードを調整する必要があるかもしれません)。
機能up
:
up () {
local path=$PWD
case $1 in
(''|'..')
cd ..; return ;;
(.)
cd .; return ;;
(/)
cd /; return ;;
(*/*)
printf '"%s" %s\n' "$1" 'contains forward slashes, up will not work' >&2
return 1 ;;
esac
if [[ $path != /* ]]; then
printf '%s\n' 'PWD is not an absolute path, up will not work' >&2
return 1
fi
until [[ $path = / ]]; do
path=${path%/*}
path=${path:-/}
if [[ ${path%"$1"} != "$path" ]] # You may add && [[ -d ${path%"$1"} ]] to
# make "up oo" fail when you are in `/foo/bar`,
# while "up foo" would succeed anyway
then
cd -- "$path"
return
fi
done
printf '%s "%s" %s\n' 'Directory' "$1" 'not found' >&2
return 1
}
完成_up
機能と説明(complete
コマンド):
_up () {
local cur last path
declare -A ancestors
cur=${COMP_WORDS[$COMP_CWORD]}
path=$PWD
if [[ $path != /* ]]; then
return 1
fi
until [[ -z $path ]]; do
path=${path%/*}
last=${path##*/}
last=${last:-/}
if [[ $last == "${cur}"* ]]; then
ancestors+=( ["$last"]= )
fi
done
COMPREPLY=( "${!ancestors[@]}" )
return
}
complete -o nospace -o filenames -F _up up
両方のコードスニペットに配置する必要があります.bashrc
。バッシュ完了完成した機能や仕様を保存することをお勧めします$XDG_DATA_HOME/bash-completion
(詳細については、インクページのFAQを参照)。~/.local/share/bash-completion
~/.bash_completion
スラッシュを含む引数は意図的に除外されます。そうでなければ(私の考えでは)foo/bar
注意を払う必要があるからですfoo///bar/./../baz
(例えば、ある種の正規化の実行)。
連想配列(declare -A
)を使用するには、Bash> = 4.0が必要です。