다음 파일이 있습니다.
Codigo-0275_tdim.matches.tsv
Codigo-0275_tdim.snps.tsv
FloragenexTdim_haplotypes_SNp3filter17_single.tsv
FloragenexTdim_haplotypes_SNp3filter17.tsv
FloragenexTdim_SNP3Filter17.fas
S134_tdim.alleles.tsv
S134_tdim.snps.tsv
S134_tdim.tags.tsv
snp
이름에 대소 문자를 구분 하는 파일 수를 세고 싶습니다 . 나는 사용하려고
grep -a 'snp' | wc -l
그러나 나는 grep
파일 내에서 검색 한다는 것을 깨달았습니다 . 파일 이름을 스캔하는 올바른 명령은 무엇입니까?
답변
snp
파일 이름 을 검색 하시겠습니까? 다음과 같이 사용되는 간단한 쉘 글로브 (와일드 카드)입니다.
ls -dq *snp* | wc -l
-q
의 버전이 ls
인식하지 못하는 경우 플래그를 생략하십시오 . “이상한”문자 (줄 바꿈 포함)가 포함 된 파일 이름을 처리합니다.
답변
유닉스와 리눅스의 복도에 조용히 서서주의 깊게 듣는다면, “새줄이 포함 된 파일 이름은 어떻습니까?”라는 귀찮은 목소리가 들립니다.
ls -d *snp* | wc -l
또는, 동등하게 ,
printf "%s\n" *snp* | wc -l
는 snp
개행 문자 가 포함 된 모든 파일 이름을 출력하고 filenames 에 개행 문자
도 포함시킨 다음 출력의 줄 수를 계산합니다. 이름이 파일 인 경우
f o o
s n p \n
b a r
. t s v
그 이름은 다음과 같이 쓰여질 것입니다
foosnp
bar.tsv
물론 두 줄로 계산됩니다.
최소한 일부 경우에 더 나은 대안이 몇 가지 있습니다.
printf "%s\n" * | grep -c snp
는를 포함하는 행을 계산 snp
하므로 foosnp(\n)bar.tsv
위 의 예제는 한 번만 계산합니다. 이것에 대한 약간의 변형은
ls -f | grep -c snp
위의 두 명령은 다음과 같은 점에서 다릅니다.
- 는
ls -f
이름이로 시작하는 파일이 포함됩니다.
; 는printf … *
하지 않는 한,하지 않는dotglob
쉘 옵션이 설정되어 있습니다. printf
쉘 내장;ls
외부 명령입니다. 따라서ls
약간 더 많은 리소스를 사용할 수 있습니다.- 쉘이 a를 처리 할 때
*
파일 이름을 정렬합니다.
ls -f
파일 이름을 정렬하지 않습니다. 따라서ls
약간의 리소스를 사용할 수 있습니다.
그러나 그들은 공통점이있다 : 그들은 모두 줄 바꿈을 포함하는 파일 이름의 존재에 잘못된 결과를 줄 것이다 및이 snp
이전과 줄 바꿈 후 모두 .
다른:
filenamelist=(*snp*)
echo ${#filenamelist[@]}
그러면을 포함하는 모든 파일 이름을 나열하는 셸 배열 변수가 생성되고 배열 snp
의 요소 수가보고됩니다. 파일 이름은 줄이 아닌 문자열로 취급되므로 포함 된 줄 바꿈은 문제가되지 않습니다. 파일 이름 목록이 셸 메모리에 있어야하므로 디렉토리가 크면이 방법에 문제가있을 수 있습니다.
또 다른 :
앞에서 말씀 드렸을 때 printf "%s\n" *snp*
, printf
명령 "%s\n"
은의 확장에서 각 인수에 대해 형식 문자열을 한 번 반복 (재사용)했습니다 *snp*
. 여기에 약간의 변화가 있습니다.
printf "%.0s\n" *snp* | wc -l
"%.0s\n"
확장의 각 인수에 대해 형식 문자열을 한 번 반복 (재사용)합니다 *snp*
. 그러나 "%.0s"
각 문자열의 처음 0자를 인쇄한다는 의미입니다. 즉, 아무것도 없습니다. 이 printf
명령은 snp
이름에 포함 된 각 파일에 대해 줄 바꿈 (즉, 빈 줄) 만 출력합니다 . 그리고 wc -l
그들을 계산합니다. 또한 .
을 설정 하여 파일을 포함 할 수 있습니다 dotglob
.
답변
요약:
“홀수”이름을 가진 파일 (새 줄 포함)에 적용됩니다.
set -- *snp* ; echo "$#" # change positional arguments
count=$(printf 'x%.0s' *snp*); echo "${#count}" # most shells
printf -v count 'x%.0s' *snp*; echo "${#count}" # bash
기술
간단한 글로브와 함께 모든 파일 이름을 일치로 snp
이름에 간단한은 echo *snp*
이 경우 충분하지만 정말로 내가 사용하는 것입니다 일치하는 세 개의 파일이 있다는 것을 보여줄 수 :
$ ls -Q *snp*
"Codigo-0275_tdim.snps.tsv" "foo * bar\tsnp baz.tsv" "S134_tdim.snps.tsv"
남아있는 유일한 문제는 파일을 세는 것입니다. 예, grep은 일반적인 해결책이며, 새로운 줄을 세는 wc -l
것도 일반적인 해결책입니다. 참고 grep -c
(수가) 정말 얼마나 많은 시간을 계산 snp
한 파일 이름이 하나 이상있는 경우, 문자열이 일치하고, snp
이름에서 문자열을, 카운트가 잘못된 것입니다.
우리는 더 잘할 수 있습니다.
간단한 해결책 중 하나는 위치 인수를 설정하는 것입니다.
$ set -- *snp*
$ echo "$#"
3
위치 인수를 변경하지 않으려면 각 인수를 한 문자로 변환하고 결과 문자열의 길이를 인쇄하십시오 (대부분의 쉘).
$ printf 'x%.0s' *snp*
xxx
$ count=$(printf 'x%.0s' *snp*); echo "${#count}"
3
또는 bash에서 서브 쉘을 피하려면 다음을 수행하십시오.
$ printf -v count 'x%.0s' *snp*; echo "${#count}"
3
파일리스트
파일 목록 (원래 질문에서 개행 문자가 추가 된 질문) :
a='
Codigo-0275_tdim.matches.tsv
Codigo-0275_tdim.snps.tsv
FloragenexTdim_haplotypes_SNp3filter17_single.tsv
FloragenexTdim_haplotypes_SNp3filter17.tsv
FloragenexTdim_SNP3Filter17.fas
S134_tdim.alleles.tsv
S134_tdim.snps.tsv
S134_tdim.tags.tsv'
$ touch $a
touch $'foosnp\nbar.tsv'
중간에 하나의 줄 바꿈이있는 파일이 있습니다.
f o o
s n p \n
b a r
. t s v
그리고 glob 확장을 테스트하려면 :
$ touch $'foo * bar\tsnp baz.tsv'
따옴표가 없으면 별표가 추가되어 전체 파일 목록으로 확장됩니다.
답변
html 파일 수를 세고 싶다고 가정 해 봅시다.
ls | grep ".html" | wc -l
“snp”의 발생 횟수를 세는 경우 :
ls | grep "snp" | wc -l