Merge every four files, Linux

I have two files stored with lists of file names:

FileA:
GSM1328513
GSM1328514
GSM1328515
GSM1328516
GSM1328545
GSM1328546
GSM1328547
GSM1328548
GSM1328609
GSM1328610
GSM1328611
GSM1328612

and:
FileB:
    Brn
    Hrt
    Lng 

I want to do this, merge every four files listed in file A, and name the concatenated file as the names of the files listed in file B: To do this manually, it looks like this:

cat GSM1328513 GSM1328514 GSM1328515 GSM1328516 > Brn
cat GSM1328545 GSM1328546 GSM1328547 GSM1328548 > Hrt
cat GSM1328609 GSM1328610 GSM1328611 GSM1328612 > Lng

Since I have a long list of files, I want to do this automatically if anyone can help. If something is unclear, please indicate.

+4
source share
6 answers

Another quick way to do this without sed:

cat FileA | while read a ; do read b ; read c ; read d ;
    echo "cat $a $b $c $d > " ; done | paste - FileB | bash

As Didier Trosset said, you can skip | bashto see what he does before it is executed.

: eval, @dshepherd :

cat FileA | xargs -n4 echo | paste - FileB | while read a b c d e ; do cat $a $b $c $d > $e ; done

: , (| bash) , (cat, xargs, paste).

+6

Shell script, ,

iter=0
while read filename
do
    stop=`expr \( $iter + 1 \) \* 4`
    iter=`expr $iter + 1`
    files=`head -n $stop fileA | tail -n 4 | tr '\n' ' '`
    cat $files > $filename
done < fileB
+2

: ,

cat FileA | xargs -n4 echo

- FileB. , , eval it ( ).

: ! GNU ( xargs ):

parallel < tempA -n4 -k --files cat | paste - tempB | xargs -n 2 mv

parallel cat 4 . stdout ( -k , ).

paste , xargs -n 2 mv .

< tempA cat tempA, .

( ) , (, bash).

+2

awk:

awk '{ORS=(NR%4?" ":"\n")}1' FileA | awk '{print "cat "$0" > "}' | paste - FileB | bash

, dshepherd :

xargs -n4 echo < FileA | awk '{print "cat "$0" >"}' | paste - FileB | bash

, .

( IMO "" ) "cat" xargs > paste:

 xargs -n4 echo cat < FileA | paste -d ">" - FileB | bash

:

  • awk, . , RN , "\n", - " ". :

    $ awk '{ORS=(NR%4?" ":"\n")}1' FileA
    GSM1328513 GSM1328514 GSM1328515 GSM1328516
    GSM1328545 GSM1328546 GSM1328547 GSM1328548
    GSM1328609 GSM1328610 GSM1328611 GSM1328612
    

    dshepherd, xargs:

    $ xargs -n4 < FileA
    GSM1328513 GSM1328514 GSM1328515 GSM1328516
    GSM1328545 GSM1328546 GSM1328547 GSM1328548
    GSM1328609 GSM1328610 GSM1328611 GSM1328612
    
  • cat >.

    $ xargs -n4 < FileA | awk '{print "cat "$0" > "}' 
    cat GSM1328513 GSM1328514 GSM1328515 GSM1328516 > 
    cat GSM1328545 GSM1328546 GSM1328547 GSM1328548 > 
    cat GSM1328609 GSM1328610 GSM1328611 GSM1328612 > 
    
  • FileB, paste - FileB ( -, .

    $ xargs -n4 < FileA | awk '{print "cat "$0" > "}' | paste - FileB
    cat GSM1328513 GSM1328514 GSM1328515 GSM1328516 >   Brn
    cat GSM1328545 GSM1328546 GSM1328547 GSM1328548 >   Hrt
    cat GSM1328609 GSM1328610 GSM1328611 GSM1328612 >   Lng
    
  • bash, bash:

    xargs -n4 < FileA  | awk '{print "cat "$0" > "}' | paste - FileB | bash
    

+2

:

cat FileA | sed 'N;N;N;s/\n/ /g;s/^/cat /;s/$/ >/;' | paste - FileB | bash

, , bash.

FileA, N, \n , prepend cat >. - FileB. bash.


sed, cat > replace.

cat FileA | sed 'N;N;N;s/\n/ /g;s/.*/cat & >/;' | paste - FileB | bash
+1
source

Using basharrays ( bash4 or later is required ). I also assume that the number of names in fileBmatch the number of names in fileA.

readarray -t gsms < FileA
for ((i=0; i<${#gsms[@]}; i+=4)); do
    read fname
    echo "${gsms[@]:i:4}" > "$fname"
done < FileB
+1
source

All Articles