Crear un servicio de conversión de codificación de texto en Automator

3

Estaba tratando de hacer un servicio de Finder para convertir fácilmente la codificación de texto de algunos archivos. Debido a que el conjunto de caracteres predeterminado para chino simplificado en Windows es el estándar nacional chino GB18030 (no el UTF-8 usado en Mac).

Con un poco de ayuda de las respuestas en servicios - Automator Obtener el nombre de archivo del archivo seleccionado - Preguntar diferente , Configuro El servicio recibe seleccionado: Archivos o carpetas en: Descubridor

Entonces, hice este script de Shell en Automator:

for f in "$@"
do
    iconv -f gb18030 -t utf-8 f > f.new
done

Sin embargo, cuando ejecuto el servicio al seleccionar f, No veo el recién creado f.new en el buscador. Supongo que he configurado mal la ruta de salida. Pero no sé cuál es la forma correcta de arreglarlo.

Automator screenshot

jackxujh
fuente
1
Para que funcione, la Pase de entrada: en el procedimiento debe ser como argumentos en lugar de a stdin .
jackxujh
He modificado mi respuesta para abordar un comentario hecho por Gordon Davisson y sugiero que use la respuesta modificada.
user3439894

Respuestas:

3

Cambio:

for f in "$@"
do
    iconv -f gb18030 -t utf-8 f > f.new
done

A:

for f in "$@"; do
    if [[ ! $(basename "$f") =~ .*\..* ]]; then
        iconv -f gb18030 -t utf-8 < "$f" > "${f}-new"
    else
        iconv -f gb18030 -t utf-8 < "$f" > "${f%.*}-new.${f##*.}"
    fi
done

Y establecer Pase de entrada: a como argumentos sobre el Ejecutar shell script acción .


Para abordar el comentario hecho por Gordon Davisson para manejar un nombre del archivo con ningún extensión , He modificado el código en mi respuesta anterior.

los código prueba el nombre del archivo parte de la nombre de ruta completo pasado a la Ejecutar script de venta acción usando un expresiones regulares Para ver si tiene una extensión, o más literalmente una . como parte de la nombre del archivo , y si no hay . en el nombre del archivo se procesa el si rama de lo contrario, procesa la otra rama .

También tenga en cuenta que utilizando un glob en vez de una expresiones regulares , p.ej.:

if [[ ! $(base name "$f") == *.* ]]; then

También trabajaría para probar una extensión. De cualquier manera el nuevo nombre de ruta completo Seguirá apropiadamente uno de estos dos ejemplos:

  • /path/to/filename se convierte en: /path/to/filename-new
  • /path/to/filename.ext se convierte en: /path/to/filename-new.ext

Nota: Esta respuesta asume nombres de ruta completamente calificados no contienen caracteres nulos y / o retornos de carro y / o saltos de línea. OMI adecuada nombres de ruta No contiene tales caracteres y no los probaré.

user3439894
fuente
@jackxujh, actualicé mi respuesta. Parece que necesita dirigir el archivo de entrada al comando y luego redirigir la salida al nuevo archivo. El archivo antiguo y nuevo debe estar en la misma ubicación ahora. Así como lo que anotó en su comentario a su pregunta.
user3439894
Después de que cambié la pasar parámetros configuración, la edición anterior de la respuesta (sin < ) comenzó a trabajar bien. Y luego te vi agregar el < marca. ¡Y también funciona!
jackxujh
Ahora el servicio hace file.txt.new con codificación de texto convertido cuando se ejecuta, pero idealmente file-new.txt sería aún mejor ¿Es eso posible también? ¡Gracias!
jackxujh
Sí, en realidad funciona de cualquier manera, pero debe ser Pase de entrada: como argumentos , que no vi en tu foto, porque lo uso automáticamente cuando ejecuto un for lazo .
user3439894
1
"${f%.*}-new.${f#*.}" solo funciona con nombres de archivo con exactamente un carácter de período (en directorios que no hacer tener periodos en el nombre). Hacer esto bien es sorprendentemente difícil, pero "${f%.*}-new.${f##*.}" (note el doble # ) maneja varios períodos correctamente (aunque todavía se confunde por los nombres de archivo sin puntos).
Gordon Davisson