
파일 이름이 두 자리 숫자로 시작하는 수백 개의 CSV 파일이 포함된 디렉토리가 있습니다 {01..84}
. 수백 >> 84이므로 일부 파일 이름은 동일한 접두어로 시작됩니다. 파일 이름이 동일한 접두사로 시작하는 파일을 연결하고 싶습니다. 이것이 내가 얻는 것입니다:
#!/bin/bash
for i in {01..84}; do
#declare array to store files with same prefix
declare -a files=()
echo "Processing $i"
for j in `ls $i*.csv`; do
#add files with same prefix to array
files=("${files[@]}" "$j")
done
#cat first file including header with the rest of the files without the headers
cat < ${files[@]:0:1} <(tail -n+2 ${files[@]:1}) > "$i".csv
done
$i
지금까지는 괜찮습니다... 단, =22(반복 가능한 오류)에서 중간에 멈추고 "==>19XXX.csv <=="(따옴표 제외)와 같은 빈 줄과 헤더로 출력 파일을 오염시킵니다.
스크립트를 충돌시키지 않고 각 접두사에 대해 깔끔하고 깨끗한 csv 파일을 얻으려면 코드에서 어떤 변경을 해야 합니까?
이러한 작업을 더 빠르고 쉽게 수행하기 위해 호출할 수 있는 미리 컴파일된 bash 유틸리티가 있습니까?
답변1
#!/bin/bash
for i in {01..84}; do
x=$(printf '%02d' $i)
set -- $x?*.csv
if [ -f "$1" ]; then
cp "$1" $i.csv
shift
if [ -f "$1" ]; then
tail -q -n +2 "$@" >> $x.csv
fi
fi
done
각 접두사에 대해 해당 접두사가 있는 파일 목록을 인수로 설정하여 $1
첫 번째 등에 액세스 하는 데 사용할 수 있습니다.
$1
파일인 경우 (주어진 접두어를 가진 파일이 없는 경우를 잡기 위해) 해당 파일을 prefix.csv에 복사합니다. 그런 다음 첫 번째 파일을 이동하고 다음 파일도 파일인지 확인하여 해당 접두사가 있는 파일이 여러 개 있는지 확인합니다. 그렇다면 명령을 통해 각 파일의 헤더 행을 건너뛰고 tail
prefix.csv에 추가하세요.
인수 목록에 여러 파일이 전달되면 헤더 줄 자체를 억제하는 옵션 이 추가됩니다 -q
.tail
tail
==> 19XXX.csv <==
해당 옵션이 솔루션에 필요한 전부일 수 있지만 -q
지나치게 복잡하고 bash
명령 출력 등을 버퍼링 해야 하므로 tail
스크립트가 조기에 중지(충돌?)되는 이유일 수 있습니다.
편집: 앞에 0이 없이 1 2 3 ...으로 확장되도록 x=$(printf '%02d' $i)
추가 되었습니다.{01..84}
답변2
#!/bin/sh
for i in {01..84}
do
cat $i*.csv > $i.csv-concat
rm $i*.csv
mv $i.csv-concat $i.csv
done
cat을 잊지 마세요. 이것은 연결 도구입니다. tail도 작업을 수행하고 헤더를 제거할 수 있습니다.
#!/bin/sh
pushd [workdir]
for i in {01..84}
do
echo $i*.csv | xargs -n 1 tail -n+2 > $i.csv-concat
rm $i*.csv
mv $i.csv-concat $i.csv
done
popd
답변3
여기에 있는 모든 사람을 위한 작업 코드 솔루션은 wurtel 기반 복사 붙여넣기:
#!/bin/bash
for i in {01..84}; do
#declare array to store files with same prefix
declare -a files=()
echo "Processing $i"
for j in `ls $i*.csv`; do
#add files with same prefix to array
files=("${files[@]}" "$j")
done
#cat first file including header with the rest of the files without the headers
if [ ${#files[@]} -gt 1 ]; then
cat <(cat ${files[@]:0:1}) <(tail -q -n+2 ${files[@]:1}) > "$i".csv
else
cat <(cat ${files[@]:0:1}) > "$i".csv
fi
done
Stéphane Chazelas는 awk를 사용합니다. 훨씬 더 깨끗합니다.
#!/bin/bash
for i in {01..84}; do
echo "processing $i"
awk 'NR==FNR||FNR>1' $i?*.csv >> "$i".csv
done