여러 개의 두 줄 구성 파일을 사용하여 작업할 때 줄 수가 다른 모든 파일을 제외할 수 있는 방법을 원합니다.
따라서 다음과 같습니다.
mv * destdir only if file contains exactly two lines
또는:
wc -l * | grep '^ *2' | xargs mv {} destdir
그러나 이 중 어느 것도 실제 작동하는 코드는 아닙니다.
이 글을 쓰면서 나는 깨달았다.하다이를 수행하는 방법이 있는데, 보기 흉하므로 아래 답변에 포함시켰습니다.
이 작업을 수행하는 쉽고 깨끗한 방법이 있습니까?
답변1
너의 서투른 해결책초보자에게는 나쁘지 않습니다. awk
행 수를 제공할 뿐만 아니라 이를 표시할 수도 있다는 사실을 놓칠 뿐입니다.출구다음을 사용하여 연결할 수 있도록 올바른 상태 코드를 사용하세요 cp
.
for file in * ; do awk 'NR==3{exit}END{exit NR!=2}' "$file" && cp "$file" /tmp; done
NR
레코드 수입니다, 그리고 제안한 대로@don_crissti대답은 NR==3
세 번째 줄을 만나면 확인을 사용하여 추가 처리를 중지할 수 있다는 것입니다.
NR!=2
awk
is true/false
값 이 흥미로워 보이지만 이것이 제대로 작동하려면 1/0
셸에서 0
성공 상태를 나타내야 합니다. &&
그 반대의 경우도 마찬가지입니다(보았을 때 반응이 얼마나 강한지에 따라 다름 !=
).
for file in * ; do awk 'NR==3{exit}END{exit NR==2}' "$file" || cp "$file" /tmp; done
답변2
, 온라인(규칙은 여전히 실행됨)을 사용할 수 있고 awk
, 그렇지 않은 경우 블록에서 ,을 사용할 수 있습니다. 행 수는 다음과 같습니다.exit
3
END
exit 1
END
2
zsh
print -rl -- *(.e_'awk "NR==3{exit}END{if(NR!=2){exit 1}}" $REPLY'_)
현재 디렉터리에 있는 두 줄의 파일이 나열됩니다. 해당 파일을 이동하려면 대상을 바꾸고 추가하세요 print -rl
. 다른 쉘의 경우:mv
for file in ./*; do [[ -f $file ]] && \
awk 'NR==3{exit};END{if(NR!=2){exit 1}}' "$file" && mv "$file" "$dest"
done
z
쉘을 사용하는 것과 같은 다른 방법
과게누 awk
:
awk 'ENDFILE{if(FNR==2){print FILENAME}}' ./*(.)
또는게누 sed
(동사 4.2.2
또는 그 이후):
sed -ns '2{$F}' ./*(.)
파일 1 과 예제를 두 줄로 나열합니다.
for f (./*(.))
sed -n '2{$Q 1};3q' $f || mv $f $dest
그들을 옮기려고.
1: 전체 입력을 거치므로 대용량 파일을 처리하는 경우에는 적합하지 않습니다. 이 경우 sed -n '2{$F};3q'
각 파일을 대상으로 지정하거나 첫 번째 awk 솔루션을 사용해야 할 수 있습니다.
답변3
파일 이름이 상당히 평범하고 :
줄바꿈과 줄 바꿈으로 구분할 수 있는 경우 다음을 수행하세요.
grep -m3 '' ./* ./*/* |
cut -d: -f1 | uniq -c |
grep -v '^ *[13] '
^이 명령은 현재 디렉터리와 두 줄만 포함하는 모든 직계 하위 디렉터리에 있는 점이 아닌 모든 파일을 나열합니다.
uniq
glob이 이미 정렬되어 있으므로 실제로 정렬에 대해 걱정할 필요가 없습니다 . 세 번째 입력 줄에서 종료하는 것이 -m
끝까지 계속하는 것보다 훨씬 빠르기 때문에 GNU axe 일치 옵션을 사용 하지만 이 옵션 없이도 작동합니다. grep
아이디어는 grep
포함된 각 줄의 파일 이름을 인쇄한 다음 출력에서 각 파일 이름이 나타나는 횟수를 계산한 다음 2보다 크거나 작은 것을 필터링하는 것입니다.
나는 임의의 소스 코드 디렉터리에 대해 이것을 실행했고, 그들 모두에는 단 두 줄만 포함하는 두 개의 파일이 있었습니다.
2 ./dex/coll.sh
2 ./jimtcl/jim-config.h.in
마지막 줄을 다음으로 바꾸는 것이 더 깔끔할 것입니다.
... |
sed -ne's/^ *2 *//p'
...하지만.
답변4
사용할 -t
대상 디렉터리 mv
옵션 xargs
:
wc -l * | sed -n 's/^[[:space:]]*2[[:space:]]\+//p' | xargs mv -t "$DESTDIR"