Acabo de ejecutar lo siguiente en bash:
uniq .bash_history > .bash_history
y mi archivo de historial terminó completamente vacío.
Supongo que necesito una forma de leer todo el archivo antes de escribirlo. ¿Cómo se hace eso?
PD: obviamente pensé en usar un archivo temporal, pero estoy buscando una solución más elegante.
bash
no colocará engaños consecutivos en su historial si configura HISTCONTROL para incluir ignoredups; ver la página de manual.Respuestas:
Recomiendo usar
sponge
de moreutils . Desde la página del manual:Para aplicar esto a su problema, intente:
fuente
Solo quería aportar otra respuesta que sea simple y no use esponja (porque a menudo no se incluye en entornos livianos).
debería tener el resultado deseado. La subshell se ejecuta antes de que .bash_history se abra para escribir. Como se explica en la respuesta de Phil P, cuando se lee .bash_history en el comando original, el operador '>' ya lo ha truncado.
fuente
$()
lugar de backticks debido a algunos problemas de escape.echo "$(fmt -p '# ' -w 50 readme.txt)" > readme.txt
hoy. Estuve buscando por mucho tiempo una solución elegante. Muchas gracias, @Hart Simha!El problema es que su shell está configurando la canalización de comandos antes de ejecutar los comandos. No es una cuestión de "entrada y salida", es que el contenido del archivo ya desapareció antes de que uniq incluso se ejecute. Va algo como:
>
archivo de salida para escribir, truncándoloHay varias soluciones, incluida la edición en el lugar y el uso de archivos temporales que otros mencionan, pero la clave es comprender el problema, qué está realmente mal y por qué.
fuente
Otro truco para hacer esto, sin usar
sponge
, es el siguiente comando:Este es uno de los trucos descritos en el excelente artículo de edición "in situ" de archivos en backreference.org.
Básicamente abre el archivo para leerlo, luego lo "elimina". Sin embargo, en realidad no se elimina: hay un descriptor de archivo abierto que apunta hacia él, y mientras permanezca abierto, el archivo todavía está disponible. Luego crea un nuevo archivo con el mismo nombre y escribe las líneas únicas en él.
Desventaja de esta solución: si
uniq
falla por algún motivo, su historial desaparecerá.fuente
usar esponja de moreutils
fuente
Este
sed
script elimina los duplicados adyacentes. Con la-i
opción, realiza la modificación en el lugar. Es delsed
info
archivo:fuente
strace
ilustración (no es que realmente importe) :-)process input > tmp && mv tmp input
es mucho más simple y más legible que usarsed
trucos simplemente para evitar un archivo temporal y no sobrescribirá mi original si falla (no sé sised -i
falla con gracia, lo haría creo que sí) Además, hay muchas cosas que puede hacer con el método de salida a archivo temporal que no se pueden hacer en el lugar sin algo aún más complicado que estesed
script. Sé que sabes todo esto, pero puede beneficiar a algunos espectadores.Como un dato interesante, sed también usa un archivo temporal (esto solo lo hace por usted):
Descripción:
el archivo temporal se
./sedPmPv9z
convierte en fd 4, y losfoo
archivos se convierten en fd 3. Las operaciones de lectura están en fd 3 y las escrituras en fd 4 (el archivo temporal). El archivo foo se sobrescribe con el archivo temporal en la llamada de cambio de nombre.fuente
Otra solución:
fuente
Un archivo temporal es más o menos, a menos que el comando en cuestión sea compatible con la edición in situ (
uniq
no, algunossed
s hacen (sed -i
)).fuente
Puede usar Vim en modo Ex:
%
seleccione todas las líneas!
ejecutar comandox
guardar y cerrarfuente
También puede usar tee, usando la salida uniq como entrada:
fuente