find
다른 명령의 출력을 기반으로 여러 파일을 처리 하려고 하는 시나리오가 있습니다 .
명령 자체는
./libopt -d test . 2>&1 | sed -rn 's/Cannot find library \"(.*?)\"/\1/p'
이것은 나에게 다음과 같은 결과를 제공합니다
libopcodes-2.25-system.so
libbfd-2.25-system.so
libz.so.1
libdl.so.2
libc.so.6
libosal.so
libarchive.so.13
libcrypto.so.1.0.0
libfreetype.so.6
libpng12.so.0
libpthread.so.0
libts-1.0.so.0
libgcc_s.so.1
libssl.so.1.0.0
libm.so.6
ld-linux.so.3
libxml2.so.2
libbz2.so.1.0
liblzma.so.5
liblzo2.so.2
libattr.so.1
libacl.so.1
libnettle.so.4
어쨌든 각 파일의 위치를 찾기 위해 이 입력을 다음 find 명령에 제공할 수 있습니까?
find /usr -name <INPUT_LINE>
답변1
문제가 되는 문자(예: 에 있는 문자)가 라이브러리 이름에 존재하지 않는다고 가정하고 IFS
목록을 반복하고 각 문자를 새 조회에 전달합니다.
./libopt -d test . 2>&1 | sed -rn 's/Cannot find library \"(.*?)\"/\1/p' \
| while read libname; do
find /usr -name "$libname"
done
그렇지 않은 경우 단일 파일 시스템 전달(위의 내용은 각 입력 파일에 대해 하나씩 수행)의 경우 이 find -name
옵션은 파일 이름 목록 일치에 적합하지 않으므로 단일 파일 시스템 검색의 출력이 에 전달될 수도 있습니다 grep
. /usr
검색 범위 좁히기라는 디렉토리 만 찾고 있습니다 lib
.
./libopt -d test . 2>&1 | sed -rn 's/Cannot find library \"(.*?)\"/\1/p' > blah
find /usr/lib /usr/*/lib -type f | grep -F -f blah
mktemp
문제가 있는 경우 blah
생성된 파일 이름을 사용하십시오. 고급 셸을 사용하면 grep
프로세스 교체 형태로 스키마 파일을 동적으로 생성할 수 있습니다.
답변2
파일 이름을 단일 정규 표현식으로 변환하고 또는(대소문자 구분 안 함) 옵션을 사용할 수 있습니다 find
.-regex
-iregex
libs=$(./libopt -d test . 2>&1 |
sed -rn 's/Cannot find library \"(.*?)\"/\1/p' |
xargs -r | sed -e 's/ /|/g ; s/\./\\./g')
[ -n "$libs" ] && find /usr -regextype egrep -iregex ".*/($libs)"
xargs
모든 파일 이름을 공백으로 구분하여 한 줄에 입력합니다. 다음 명령은 sed
공백을 |
and로 변경합니다. 이 명령은 $libs가 비어 있지 않은 경우에만 실행됩니다..
\.
find
참고: 출력할 파일 이름이 너무 많으면(수천) 명령 ./libopt
이 xargs
2개 이상의 줄을 출력하고 $libs가 너무 커서 하나의 명령줄에 맞지 않아 중단됩니다. 이것이 가능하다면(출력 결과를 고려하면 그럴 것 같지 않습니다) 다음과 같이 루프에서 and 를 ./libopt
실행하여 xargs | sed
문제를 해결할 수 있습니다.find
libs=$(./libopt -d test . 2>&1 | sed -rn 's/Cannot find library \"(.*?)\"/\1/p')
for re in $(echo "$libs" | xargs | sed -e 's/ /|/g ; s/\./\\./g') ; do
find . -regextype egrep -iregex ".*/($re)"
done
답변3
그리고 zsh
:
files=(
${(f)"$(./libopt -d test . 2>&1 |
sed -rn 's/Cannot find library \"(.*?)\"/\1/p')"})
glob=('$files['{1..$#files}']')
eval "paths=(**/(${(j:|:)glob})(D.))"
ls -ld -- $paths
비슷한 질문에 대한 답변을 확인하세요.https://unix.stackexchange.com/a/265815설명이 필요하거나 없는 경우 몇 가지 대안을 확인하세요 zsh
.