:es otro nombre para true. Ambas son conchas incorporadas en bash, pero no hay /bin/:, solo a /bin/true. La redirección de salida provoca el shell al open(2)archivo con O_CREAT|O_TRUNC. Si no se escribe nada, permanece en longitud cero.
Poner esas dos piezas juntas :> filees un modismo bastante común para truncar archivos. Sin embargo, la mayoría de la gente trataría de hacerlo menos extraño escribiendo : >file.
Como me preguntaste en un comentario sobre la segunda línea, convertiré mis comentarios en una respuesta. (aunque no hiciste esto en tu pregunta).
La segunda línea es un bucle que lee líneas de otherfilealgunas variables con nombre. El cuerpo del bucle se usa echopara imprimirlos con ;separadores en lugar de cualquier espacio en blanco que tenían antes. filese cierra y se vuelve a abrir (para agregar) cada iteración, porque la redirección está dentro del bucle. El uso while ...;do read -r ...;done <otherfile >filesería menos difícil y evitaría la necesidad de truncar primero el archivo. read -rno come \como un personaje de escape.
El procesamiento de texto en bash es bastante lento. Parte de eso es inevitable: readtiene que ir un byte a la vez (una read(2)llamada al sistema por byte) para evitar sobrepasar el final de una línea. Sería mejor usar la herramienta adecuada para el trabajo:
awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile >file
--significa que su script no se rompe si otherfilese le llama algo tonto --version.
Establecer el Separador de campo de salida en ;significa que puede pasar varios campos como argumentos para imprimir. Shell readasigna todo el resto de la línea con espacios en blanco a la última variable, pero no hay forma de decirle a awk que solo se divida en 5. Si eso es importante, tal vez solo siga usando un bucle bash, porque no es conveniente en awk. Perl lo hace fácil, ya que splitpuede tomar un argumento de campos máximos, pero es mucho más lento para iniciar que awk.
En realidad, resultó no ser tan difícil, solo una expresión regular fea para escribir. Para obtener el resto de la línea en lugar de $5en awk, recorrer los campos aún pierde su espacio en blanco original. Mi primera idea viable es usar gensuben $0(toda la línea) para eliminar los primeros 4 campos (es decir, sin espacio seguido de espacio), dejando todo lo demás:
awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file
Lo hice bien en el primer intento, pero el hecho de que estaba impresionado conmigo mismo por eso dice algo sobre la legibilidad de ese código awk. >. <
Tenga en cuenta que es igual printque antes, pero con tailen lugar de $5.
echo 'A B c DD e f g f' |
awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
print $1, $2, $4, tail, $3 }'
A;B;DD;e f g f;c
Esto sería más impresionante si pudiera copiar / pegar el literal y mostrar que apareció en la salida. Escriba uno en bash con ^ Q. ctrl-Q significa Citar la siguiente pulsación de tecla como un carácter literal, ya que la edición de línea al estilo de emacs de bash es la misma que la de emacs real para esto.
http://mywiki.wooledge.org/BashFAQ tiene algunas cosas útiles acerca de las secuencias de comandos de manera que no se rompan sin importar qué datos o nombres de archivos arrojes a la secuencia de comandos.
:>que no es un solo operador. Puede ser más fácil de entender si lo lees como en su: > filelugar.