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

Estaba tratando de crear un servicio Finder para convertir fácilmente la codificación de texto de algunos archivos. Porque el juego de caracteres predeterminado para chino simplificado en Windows es el estándar nacional chino GB18030 (no el UTF-8 que se usa en Mac).

Con un poco de ayuda de las respuestas en los servicios - Automator Obtener el nombre de archivo del archivo seleccionado - Preguntar diferente , configuro Servicio recibe seleccionado: Archivos o carpetas en: Finder

Luego, 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.newen Finder. Supongo que he configurado mal la ruta de salida. Pero no sé cuál es la forma correcta de solucionarlo.

Captura de pantalla de Automator

Para que funcione, la entrada Pass: en el procedimiento debe ser como argumentos en lugar de stdin .
Modifiqué mi respuesta para abordar un comentario hecho por Gordon Davisson y sugiero que use la respuesta modificada en su lugar.

Respuestas (1)

Cambiar:

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 configure Pass input: como argumentos en la acción Run Shell Script .


Para abordar el comentario hecho por Gordon Davisson para manejar un nombre de archivo sin extensión , modifiqué el código en mi respuesta anterior.

El código prueba la parte del nombre de archivo del nombre de ruta completamente calificado pasado a la acción Ejecutar secuencia de comandos de venta usando una expresión regular para ver si tiene una extensión, o más literalmente, como parte del nombre de archivo , y si no hay ninguna en el nombre de archivo , procesa la if branch , de lo contrario procesa la otra rama ...

También tenga en cuenta que usar un glob en lugar de una expresión regular , por ejemplo:

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

También funcionaría para probar una extensión. De cualquier manera, el nuevo nombre de ruta completamente calificado seguirá uno de estos dos ejemplos:

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

Nota: Esta respuesta asume que los nombres de ruta completamente calificados no contienen caracteres nulos ni retornos de carro ni saltos de línea. En mi opinión, los nombres de ruta adecuados no contienen tales caracteres y no los probaré.

@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 el nuevo deben estar en la misma ubicación ahora. Además de lo que anotó en su comentario a su pregunta.
Después de cambiar la configuración de los parámetros de paso , la edición anterior de la respuesta (sin <) comenzó a funcionar bien. Y luego vi que agregaste la <marca. ¡Y también funciona!
Ahora el servicio funciona file.txt.newcon codificación de texto convertido cuando se ejecuta, pero lo ideal file-new.txtsería que fuera aún mejor. ¿Es eso posible también? ¡Gracias!
Sí, en realidad funciona de cualquier manera, sin embargo, debe ser Pass input: as arguments , que no miré en su imagen, porque lo uso automáticamente cuando ejecuto un for bucle .
@jackxujh, actualicé mi respuesta para abordar su comentario "Ahora el servicio crea 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?"
Agradezco la ayuda y la paciencia! Lamento molestarlo con esta simple práctica de expresiones regulares , de la que acabo de aprender más de su respuesta.
@jackxujh, No hay problema, para eso estamos aquí, ¡para ayudar y aprender! :) Por cierto, lea la sección Expansión de parámetros en la página del manual BASH.
"${f%.*}-new.${f#*.}"solo funciona en nombres de archivo con exactamente un carácter de punto (en directorios que no tienen puntos en el nombre). Hacer esto correctamente es sorprendentemente difícil, pero "${f%.*}-new.${f##*.}"(tenga en cuenta el doble- #) maneja múltiples puntos correctamente (aunque todavía se confunde con los nombres de archivo sin puntos).
@Gordon Davisson, es bueno saberlo. Si desea editar eso en la respuesta, no dude en hacerlo.
@ user3439894 Seguí adelante y lo amplié para manejar prácticamente cualquier cosa; siéntase libre de revertir si cree que es demasiado cambio de su versión.
@Gordon Davisson, ¡Gracias por señalar un problema en el código! He modificado la respuesta para abordar su primer comentario de una manera diferente a su edición, lo siento. Por cierto, accidentalmente omití una #en mi respuesta original modificada para abordar a jackxujh que quería -newestar antes de la extensión, realmente fue un error tipográfico ya que cambié "${filename##*.}"a "${f#*.}"cuando, por supuesto, debería haber sido "${f##*.}". Sin embargo, incluso con él, fallaría si el nombre del archivo no tuviera una extensión. Así que probarlo debería haber sido parte del código y lo he cambiado a un método que prefiero. ¡Gracias de nuevo!