3 votos

Dividir un archivo csv mediante el servicio Automator (menú contextual del Finder)

Estoy intentando crear un Automator Servicio para Buscador El menú contextual del botón derecho del ratón puede dividir cualquier archivo csv seleccionado, copiando al mismo tiempo la cabecera original en la parte superior de cada archivo.

Mi intento actual es hacer que Automator ejecute este 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??

Este script dividirá MY_CSV_FILE.csv en nuevos archivos con un máximo de 50 líneas mientras se copia la cabecera original en la parte superior de cada archivo. Los nuevos archivos tendrán el nombre original añadido con xaa , xab , xac etc.

En cuanto a la configuración de Automator, este es el Servicio en el que estoy trabajando actualmente. El problema ahora mismo es que no puedo pasar el Archivo Seleccionado en Finder al Bash script.

enter image description here

Fíjate en eso:

  • El servicio lo recibe: archivos o carpetas en Finder.app .
  • Pasa la entrada al Shell script: como argumentos .
  • He eliminado #!/bin/bash desde la parte superior de la Shell script y pon la Shell en: /bin/bash .
  • Cambié MY_CSV_FILE.csv para "$f" - No estoy seguro de que eso sea correcto.

¿También tengo que especificar la ruta usando algo como "$@" tanto para el archivo de entrada como para los archivos de salida resultantes? No he hecho algo como esto antes, así que no estoy muy familiarizado con esa variable y "$f" para el caso.

¿Cómo puedo hacer que esto funcione? Me gustaría que los archivos resultantes aparecieran en la misma carpeta que el archivo que selecciono para ejecutar el Servicio, a través del menú del botón derecho del Finder. Sería aún mejor si el Servicio sólo aceptara archivos csv.

enter image description here

7voto

user3439894 Puntos 5883

Yo escribiría el código un poco diferente, y aquí hay un ejemplo de cómo lo haría:

#!/bin/bash

for f in "$@"; do
    if [[ -f $f ]]; then
        d="$(dirname "$f")"
        n="$(basename "$f")"
        t='/tmp'
        if [[ ${n##*.} =~ [cC][sS][vV] ]]; then
            head -1 "$f" > $t/h.tmp
            tail -n +2 "$f" | split -a 3 -l 50 - $t/tmp.
            i=1
            for s in $t/tmp.a??; do
                fn="$d/${n%.*}.$(printf '%03d' $i).csv"
                if [[ ! -f $fn ]]; then 
                    cat $t/h.tmp $s > "$fn"
                    ((i++))
                else
                    rm $t/h.tmp $t/tmp.a??
                    echo "The file '"$fn"' already exists!"
                    exit
                fi
            done
            rm $t/h.tmp $t/tmp.a??
            echo ''
        fi
    fi
done
  • Tal como está codificado actualmente, maneja uno o más archivos pasado a la servicio .
  • Asegura que el objeto que se actúe es un archivo no es un directorio .
  • Asegura que el archivo tiene un .csv extensión (independientemente del caso de la extensión).
  • Crea el archivos temporales en: /tmp
  • Comprueba que el nombre de archivo de salida no existe ya, y si existe, se limpia y se sale.
  • Escribe en un archivo con un nombre de archivo incrementado numéricamente Por ejemplo file.001.csv , file.002.csv etc., en el mismo directorio como el archivo(s) pasado a la servicio .
  • Elimina el archivos temporales creado en: /tmp
  • Tal y como está codificado, gestiona archivos con un número de líneas de hasta 49.950 archivos divididos en 50 líneas, sin contar la cabecera.
    • Tenga en cuenta que no se ha codificado ningún tratamiento de errores para el recuento total de líneas del archivo de origen Sin embargo, podría añadirse fácilmente.
    • O fácilmente modificable para manejar archivos con un número de líneas de hasta 499.950 archivos divididos en 50 líneas, sin contar la cabecera, cambiando -a 3 de la split comando a -a 4 y '%03d' de la printf comando a '%04d' . También cambiarías $t/tmp.a?? en
      for s in $t/tmp.a??; do y rm $t/h.tmp $t/tmp.a?? a: $t/tmp.a???

También añadiría un Ejecutar Apple script acción a la servicio con lo siguiente código :

on run {input, parameters}
    if (item 1 of input) is "" then
        display notification "Splitting of the target file(s) is finished!" with title "Split CSV File(s)"
    else
        display notification (item 1 of input as string) with title "Split CSV File(s)"
    end if
end run

Esto permite que el salida de la echo comandos en el Ejecutar Shell script acción para mostrar una notificación si un archivo de salida ya existe o cuando la división está terminada.

Tenga en cuenta que si bien la notificación puede hacerse desde el Ejecutar Shell script acción utilizando osascript Sin embargo, lo hice así porque era más fácil de codificar.


Automator Service Workflow

Esto se probó en un archivo llamado archivo.csv en Buscador que tiene 200 líneas, y las imágenes de abajo muestran lo que fue creado por el Ejecutar Shell script acción parte de la Automatizador servicio cuando se ejecuta en el archivo .

CSV File in Finder

Contents of split CSV File in TextEdit

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X