예를 들어 youtube-dl을 컴퓨터에 설치하는 방법은 다양합니다. 실수로 여러 가지 방법으로 여러 번 다운로드/설치했기 때문에 $PATH 디렉토리, , 및 /usr/local/bin/youtube-dl
에 여러 개의 youtube-dl 실행 파일이 생성되었습니다 . 따라서 업그레이드된 버전 "2021.01.03"을 설치했는데도 $PATH의 다른 디렉터리에 있는 youtube-dl이 어떻게든 덮어썼기 때문에 "2020.07.28"로 표시됩니다./home/username/.local/bin/youtube-dl
/usr/local/bin/youtube-dl
youtube-dl --version
그래서 여기서는 $PATH에서 동일한 이름을 가진 모든 설치된 파일을 확인하여 해당 버전을 즉시 확인하고 어떤 것이 최신인지, 최신인지, 어떤 것을 제거해야 하는지 확인하고 싶습니다. 그렇다면 이를 수행할 수 있는 방법이나 CLI 도구가 있습니까? 감사해요.
답변1
대화형으로는 다음을 사용합니다.
ls -l $(type -ap youtube-dl)
youtube-dl
내 $PATH에서 모든 프로그램의 위치와 타임스탬프를 찾습니다 .
물론 이름에 공백이 있는 실행 파일에서는 작동하지 않지만 youtube-dl
그 중 하나는 아닙니다.
답변2
PATH 디렉터리에 순차적으로 액세스하고 실행할 파일 위치를 나열하려면 다음 which
명령을 사용할 수 있습니다.
$ which -a command_name
답변3
다음 스크립트는 변수에 의해 나열된 디렉터리에 있는 중복 실행 파일 목록을 출력합니다 $PATH
.
탭으로 구분된 2열 실행 파일 목록을 생성하여 이를 수행합니다. 여기서 첫 번째 열은 디렉터리 경로 이름이고 두 번째 열은 실행 파일의 파일 이름입니다.
awk
이 목록은 각 실행 파일이 발견된 횟수를 세고 탭으로 구분된 문자열에서 각 실행 파일에 대한 모든 디렉터리 경로 이름을 수집하는 간단한 프로그램으로 읽혀집니다 .
마지막으로 awk
코드는 정확한 이름이 여러 번 발견된 각 실행 파일과 해당 파일이 발견된 디렉터리 경로 이름의 탭으로 구분된 목록을 출력합니다. 검색된 순서대로 디렉터리가 나열되며, 다음 디렉터리에서 실행 파일이 선택됩니다.첫 번째명령줄에서 명시적인 경로 없이 사용하면 디렉터리(현재 값이 지정됨 $PATH
)가 나열됩니다.
#!/bin/sh
# turn off filename globbing, and
# split strings in unquoted variables on colons
set -f; IFS=:
# set the positional parameters to the list of
# directories in the PATH variable
set -- $PATH
# turn on filename globbing again
# (leave IFS as is, it won't affect anything else here)
set +f
# loop over those directories and do the things
for dir do
for pathname in "$dir"/*; do
[ -x "$pathname" ] && printf '%s\t%s\n' "$dir" "${pathname##*/}"
done
done |
awk -F '\t' '
{
dir[$2] = ( dir[$2] == "" ? $1 : dir[$2] "\t" $1 )
count[$2]++
}
END {
for (util in dir)
if (count[util] > 1)
printf "%s\t%s\n", util, dir[util]
}'
내 OpenBSD 시스템에서 실행되는 예입니다. 출력을 전달하여 column -t
형식을 적절하게 지정한 다음 정렬합니다.
$ sh script | column -t | sort
banner /usr/bin /usr/games
bash /home/myself/local/bin /usr/local/bin
bashbug /home/myself/local/bin /usr/local/bin
chgrp /bin /usr/sbin
chown /usr/sbin /sbin
clang /usr/bin /usr/local/bin
clang++ /usr/bin /usr/local/bin
clang-cpp /usr/bin /usr/local/bin
ld.lld /usr/bin /usr/local/bin
llvm-config /usr/bin /usr/local/bin
python3 /home/myself/local/bin /usr/local/bin
python3.8 /home/myself/local/bin /usr/local/bin
sysctl /usr/sbin /sbin
zsh /home/myself/local/bin /usr/local/bin
명령줄에서 실행 하면 명령줄 에서 bash
실행 /home/myself/local/bin
되고 .bash
/usr/local/bin
답변4
동일한 이름을 가진 설치된 파일을 모두 확인하고 싶습니다.
$PATH
여기에 또 다른 제안이 있습니다. find
across를 사용하여 $PATH
파일 이름을 얻고 awk
중복 항목과 일치시키는 것입니다. 원한다면 한 줄로 묶을 수도 있지만 가독성을 위해 여러 줄에 걸쳐서 표시했습니다.
( IFS=:; find $PATH -maxdepth 1 -type f ) | # See below for alternative without maxdepth
awk -F/ '
{
p[$NF] = p[$NF] "\n" $0; # Save the pathname ($NF is last component)
h[$NF] ++ # Count this instance of the filename
}
END {
for (f in h) {
if (h[f] >1) { print p[f] } # Print list iff we have multiple hits
}
}
'
find
아무런 조치가 없으면 첫 -maxdepth
번째 줄을 다음으로 바꿀 수 있습니다.이 확장
( IFS=:; for dir in $PATH; do find dir ! -path dir -prune -type f; done ) |
읽을 수 없지만 한 줄로 묶인 버전
(IFS=:; find $PATH -maxdepth 1 -type f)|awk -F/ '{p[$NF]=p[$NF]"\n"$0;h[$NF]++}END{for(f in h){if(h[f]>1){print p[f]}}}'