Search code examples
bashmacosautomator

Split csv file using Automator Service (Finder Context Menu)


I am trying to create an Automator Service for Finder's Right-Click Context Menu that can split any selected csv file, whilst copying in the original header at the top of every file.

My current attempt is to make Automator run this Bash Shell Script:

#!/bin/bash

FILE=$(ls -1 | grep MY_CSV_FILE.csv)
NAME=${FILE%%.csv}

head -1 $FILE > header.csv
tail -n +2 $FILE > data.csv

split -l 50 data.csv

for a in x??
    do
        cat header.csv $a > $NAME.$a.csv
    done

rm header.csv data.csv x??

This script will split MY_CSV_FILE.csv into new files with max 50 lines while copying in the original header at the top of every file. The new files will have the original name appended with xaa, xab, xac etc.

Regarding the Automator setup, this is the Service I'm currently working on. The problem right now is that I'm unable to pass the Selected File in Finder to the Bash script.

enter image description here

Notice that:

  • Service receives: files or folders in Finder.app.
  • Pass input to Shell script: as arguments.
  • I have removed #!/bin/bash from the top of the Shell Script and set the Shell to: /bin/bash.
  • I switched MY_CSV_FILE.csv for "$f" – not sure if that's correct.

Do I also need to specify the path using something like "$@" for both the input file and the resulting output files? I haven't done something like this before, so I'm not really familiar with that variable and "$f" for that matter.

How could I make this work? I'd like the resulting files to appear in the same folder as the file I select to run the Service on, via the Finder Right-Click Menu. It would be even better if the Service only accepted csv files.

enter image description here


Solution

  • I edit your script to satisfy the needs

    set -e
    
    for FILE in "$@"
    do
            #must be a file size bigger than zero with extension csv
            if test -f ${FILE}  && test -s ${FILE} &&  test ${FILE: -4} == ".csv" ; then
                    NAME=${FILE%%.csv}
    
    
                    head -1 ${FILE} > header.csv
                    tail -n +2 ${FILE} > data.csv
    
                    split -l 50 data.csv
    
                    for a in x??
                    do
                            cat header.csv ${a} > ${NAME}.${a}.csv
                    done
    
                    rm header.csv data.csv x??
    
            fi
    done
    

    Note the origin script is not so safe, if you have such files in your directory header.csv data.csv or any file that matches glob pattern x??. All these files will be deleted when rm header.csv data.csv x?? executed.