파이프라인 모드 입력 찾기 명령

파이프라인 모드 입력 찾기 명령

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

참고: 출력할 파일 이름이 너무 많으면(수천) 명령 ./liboptxargs2개 이상의 줄을 출력하고 $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.

관련 정보