저는 Linux를 처음 사용하지만 이것이 가능한지 알고 싶습니다. 디렉토리에 파일 이름 접미사가 붙은 파일이 있는지 확인하고 싶습니다. .bam
확인할 디렉토리가 수백 개 있습니다. 저는 이 작업을 수동으로 수행하고 싶지 않습니다. 따라서 모든 디렉토리를 확인한 다음 출력하는 것이 가능합니까?해당 파일 목록이 없습니다?
답변1
존재하다 zsh
:
if ()(($#)) **/*.bam(ND.Y1)); then
print There is at least one regular file in here whose name ends in .bam
fi
directories_without_bam=(
**/*(ND/^e['()(($#)) $REPLY/*.bam(ND.Y1)'])
)
if (( $#directories_without_bam )); then
print "Directories without bam files:"
printf ' - %s\n' $directories_without_bam
fi
현재 작업 디렉터리( ) 자체는 보지 않고 .
그 아래에 있는 디렉터리만 살펴봅니다. 변경 사항 도 고려됩니다 **/*
. ){.,**/*}
.
답변2
bash
셸을 사용하면 현재 디렉터리에 로 끝나는 이름이 포함되어 있는지 테스트하고 .bam
, 그렇지 않은 경우 다음과 같이 메시지를 인쇄할 수 있습니다.
shopt -s dotglob nullglob
set -- ./*.bam
[ "$#" = 0 ] && echo 'nothing found'
쉘 dotglob
옵션은 *
숨겨진 이름 일치를 허용하며 nullglob
일치하는 항목이 없으면 패턴을 변경하지 않고 그대로 두는 대신 패턴을 제거합니다.
set
패턴을 확장하고 위치 인수 목록을 일치하는 이름으로 설정할 수 있습니다 . 위치 인수 목록의 길이가 0 이면 $#
패턴과 일치하는 이름이 없습니다.
find
이 코드를 현재 디렉터리와 그 아래의 모든 디렉터리에 적용 할 수 있습니다 .
find . -type d -exec bash -O dotglob -O nullglob -c '
for d do
set -- "$d"/*.bam
[ "$#" = 0 ] && printf "%s\n" "$d"
done' bash {} +
이것은 처음부터 모든 디렉토리를 재귀적으로 찾아서 .
주어진 인라인 bash
스크립트에 일괄적으로 공급합니다. 스크립트는 지정된 디렉터리 경로를 반복하고 set
명령과 테스트를 순서대로 적용하여 일치하는 이름을 생성하지 않은 디렉터리의 경로 이름을 인쇄합니다.
셸에는 failglob
패턴이 아무것도 일치하지 않을 때 실패를 생성하는 셸 옵션도 있습니다. 이를 사용하여 코드를 조금 더 짧게(작게!) 만들 수 있지만 읽기도 더 어렵게 만들 수 있습니다.
find . -type d -exec bash -O dotglob -O failglob -c '
for d do
(set -- "$d"/*.bam) 2>/dev/null || printf "%s\n" "$d"
done' bash {} +
답변3
@waltinator의 comm
유틸리티 아이디어 와 유사하게 grep
표준 입력에서 문자열 세트를 제거하는 데 사용할 수 있습니다.
$ find mypath/ -type d |
grep -Fvxf <(find mypath/ -name \*.bam -type f -exec dirname {} \; | sort | uniq)
구문을 설명하기 위해 파이프의 왼쪽은 그 아래의 모든 디렉터리 목록을 만듭니다 mypath/
. 오른쪽의 괄호에 주목하세요. 수학과 마찬가지로 이 부분이 먼저 완료됩니다. 아래의 모든 파일을 find
찾지 만 각 파일의 디렉터리 경로만 인쇄합니다. 그런 다음 해당 출력이 편집되고(아마도 불필요하지만 시간이 거의 걸리지 않는 것 외에는 아무런 해를 끼치지 않음) 각 디렉터리 이름이 한 번만 나타나도록 편집됩니다. ing은 동일한 디렉터리 이름을 여러 번 검색하는 것을 방지하기 위한 예의입니다 . 제거할 디렉터리 목록이 있으면 입력 스트림(모든 디렉터리의 마스터 목록)에서 괄호 안의 명령 대체에 의해 생성된 각 디렉터리(파일 위치 목록)를 제거합니다. 나머지 출력은 파일이 포함되지 않은 디렉터리 집합입니다 .*.bam
mypath/
sort
uniq
uniq
grep
grep
*.bam
*.bam
답변4
@waltinator가 의견에서 말했듯이 find 명령을 사용할 수 있습니다.
find /your/path -type d '!' -exec sh -c 'ls -1 "{}" | egrep -i -q "^.*\.bam$"' ';' -print
설명을 찾을 수 있습니다여기.
샘플 출력:
$ find /usr/libexec -type d '!' -exec sh -c 'ls -1 "{}"|egrep -i -q "^.*\.so$"' ';' -print
/usr/libexec
/usr/libexec/emacs
/usr/libexec/emacs/29.1
/usr/libexec/emacs/29.1/x86_64-pc-linux-gnu
/usr/libexec/man-db
/usr/libexec/gcc
/usr/libexec/gcc/x86_64-pc-linux-gnu
/usr/libexec/gcc/x86_64-pc-linux-gnu/13/plugin
/usr/libexec/git-core
/usr/libexec/git-core/mergetools
/usr/libexec/podman
/usr/libexec/nullmailer