기본적으로 search 명령과 비슷한 것을 얻으려고 하는데 $PATH
디렉터리 목록이 다르고 검색 중인 파일이 실행 가능하지 않습니다.
디렉토리 목록은 고정되어 있으며(PATH와 같은 형식의 변수로 압축할 수 있음) 하위 디렉토리로 드롭다운하고 싶지 않습니다. bash에 complete
옵션이 있다는 것을 어렴풋이 기억하지만 해당 섹션을 끝까지 읽었지만 찾지 못했습니다. 나는 가까운가?
어쩌면 다음과 같을 수도 있습니다(파일이 있다고 가정 ~/lib
).
> filepath -p ".:/etc:$HOME/lib:$HOME/bin" foo
/home/alexis/lib/foo
which
즉, or 와 같은 것을 찾고 있지만 which -a
실행 파일에만 국한되어서는 안 됩니다. 실행 파일만 검색하면 안 되지만 $PATH
문제를 해결할 수 있습니다 ;-).
답변1
find
이미 여러 검색 경로를 지원합니다.
find . /etc ~/lib ~/bin -maxdepth 1 -name '*foo*'
또는 사용fd
find보다 더 빠르고 기능이 풍부하며 더 아름답습니다.
fd --max-depth=1 foo . /etc ~/lib ~/bin
또 다른 간단한 방법이지만 공백이나 줄 바꿈이 있는 파일에서는 작동하지 않을 수 있습니다.
SearchPaths=(/etc ~/lib ~/bin)
shopt -s nullglob
eval printf "%s " "${SearchPaths[@]/%/*foo*}"
Bash 배열을 사용하여 직접 파일 확장을 수행하는 더 쉬운 방법을 본 것 같지만 지금은 기억이 나지 않습니다.
답변2
bash 함수를 GNU의 래퍼로 사용할 수 있습니다 find
.
filepath () {
local fp_path=${FP_PATH:-".:/etc:$HOME/lib:$HOME/bin"} fpath fquit=-quit
local usage="usage: filepath [-a] [-p path[:path...]] expr"
OPTIND=1
while getopts :ap: opt; do
case $opt in
a) fquit=
;;
p) fp_path=$OPTARG
;;
*) echo "$usage" >&2
return 1
esac
done
shift $((OPTIND-1))
if [ -z "$1" ]; then
echo "$usage" >&2
return 1
fi
IFS=: read -r -a fpath <<<"$fp_path"
find "${fpath[@]}" -maxdepth 1 \( -type f -o -type l \) -name "$1" -print $fquit 2>/dev/null
}
기본 검색 경로는 함수의 첫 번째 줄에 정의되며 :
구분 기호로 사용됩니다. 환경 변수 FP_PATH
나 옵션 으로 재정의될 수 있습니다 -p
. 옵션을 사용하지 않는 한
find
첫 번째 결과를 인쇄한 후 종료합니다 . -a
검색은 일반 파일과 기호 링크로 제한되며 필요에 따라 옵션을 조정합니다.
예:
$ mkdir -p ~/bin /tmp/etc
$ touch ~/bin/foo /tmp/foo /tmp/etc/foo
$ filepath
usage: filepath [-a] [-p path[:path...]] expr
$ filepath -a -p /tmp:/tmp/etc 'fo*'
/tmp/foo
/tmp/etc/foo
$ filepath -p /tmp:/tmp/etc 'fo*'
/tmp/foo
$ FP_PATH=/tmp filepath foo
/tmp/foo
$ filepath foo
/home/freddy/bin/foo
답변3
디렉토리 목록을 배열( bash
)에 저장하려는 경우 다음과 같은 코드를 사용할 수 있습니다.
# Maybe in ~/.bashrc
filefindlist=(. /etc "$HOME/lib" "$HOME/bin" src/*)
filefind() {
local ff
for ff in "${filefindlist[@]}"
do
if [ -d "$ff" ] && [ -f "$ff/$1" ]
then
printf '%s\n' "$ff/$1"
return 0
fi
done
return 1
}
용법
filefind program.c
filefindlist
배열을 정의할 때 모든 변수와 쉘 전역 변수(와일드카드)가 평가됩니다. 따라서 src/one
나중에 배열을 생성 하면 으로만 확장됩니다 src/two
. 그러나 다음에 배열을 정의할 때는 및 가 포함됩니다 .src/*
src/one
src/one
src/two
질문에서 제안된 내용을 정확하게 구현하려면 다음 접근 방식을 사용할 수 있습니다.
filefind() {
local fl="$FILEFINDLIST" fp ff
[ "$1" = '-p' ] && fl="$2" && shift 2 # Override default search list
readarray -d: -t fp <<<"$fl" # Convert to array
for ff in "${fp[@]}"
do
if [ -d "$ff" ] && [ -f "$ff/$1" ]
then
printf '%s\n' "$ff/$1"
return 0 # Only print first match
fi
done
return 1
}
용법
FILEFINDLIST='.:$HOME/lib:$HOME/bin'
filefind -p ".:/etc:$HOME/lib:$HOME/bin" program.c
filefind program.c
답변4
그리고 zsh
:
filepath() print -rC1 -- ${(s[:])^1}/$^@[2,-1](N)
그 다음에:
$ filepath .:/etc:$HOME/lib:$HOME/bin ls issue python
/etc/issue
/home/chazelas/lib/python
/home/chazelas/bin/ls