web-dev-qa-db-ja.com

Linux:指定された検索パスから最初の結果を見つける

$ PATHとよく似ていますが、必ずしも$ PATHではない、コロンで区切られたパスリストがある場合

そのリストで特定のファイル名を検索したいのですが、最初に一致するパスのみが必要です。

次のLinuxコマンドを検討しました。

  • which:バイナリでのみ機能し、$ PATH変数でのみ機能します
  • whereis:特定の種類のファイルで機能し、$ PATH変数でのみ機能します
  • find:コロンで区切られたパスリストをサポートせず、複数の結果を返します

これが私が試したいくつかのことです:

  1. 私は次の戦略でwhereisを使おうとしました

    env WHEREIS="`which whereis`" PATH="$MY_PATH_LIST" $WHEREIS "$TARGET_FILE"
    

    そしてこれはほとんど機能します。ただし、任意のファイルタイプの結果を返すようには見えません。また、複数の結果を扱いにくい形式で返します。

  2. whichを動作させることができます

    env WHICH="`which which`" PATH="$MY_PATH_LIST" $WHICH "$MY_TARGET_FILE"
    

    非実行可能ファイルを許可するように強制するコマンドラインオプションがあった場合。

  3. 次に、findで問題を解決しようとしました。まず、正規表現を使用してパスリストを展開しました(コロンをスペースに置き換えます)。次に、findを呼び出すと、正しく機能します。ただし、すべてのパスを検索します。良い結果が得られたら、検索を早く停止するように指示する方法が見つからないようです。

    私はこれを機能させました

     find ${MY_PATH_LIST//[:]/ } -name "$MY_TARGET_FILE" | head -n 1
    

    ただし、findはまだ徹底的な検索を行っているため、完了するまでに長い時間がかかります。

    これは、さまざまなパラメーターを使用して何度も実行されるため、より高速に実行する(最初の結果で終了する)ために必要です。

誰かが提案するより良い解決策を持っていますか?

すべてが失敗した場合、私は非bashソリューションを書くことができることに注意してください。今すぐ書く既存のツールを使用した簡単な解決策を望んでいます。

5
Kevin A. Naudé

単にテストするスクリプトを使用することができます(-e)ファイルが存在する場合、最初のファイルが見つかったときに停止します。

#!/bin/bash
[[ $# -gt 0 ]] || { echo "Usage: $0 <filename> [pathspec]" >&2 ; exit 1 ; }
if [[ $# -gt 1 ]] ; then
        P="$2"
else
        P="$PATH"
fi

IFS=:
for DIR in $P ; do
        if [[ -e "$DIR/$1" ]] ; then
                echo "$DIR/$1"
                exit 0
        fi
done

例:

$ ./search.sh 
Usage: ./search.sh <filename> [pathspec]

$ ./search.sh ls
/Users/danielbeck/bin/ls

$ ./search.sh pwd
/bin/pwd

$ ./search.sh ls /bin
/bin/ls

$ ./search.sh ls /usr/bin:/bin
/bin/ls
3
Daniel Beck

Headを使用して、findコマンドの最初の結果を取得します。

find `echo colon:separated:directories | sed 's/:/ /g'` -name filename | head -n1

または関数内:

$ function findin { find `echo $1 | sed 's/:/ /g'` -name $2 | head -n1; }
$ findin this:that:other filename
0
Daniel Patru