Řešení 1:
echo "$(uniq .bash_history)" > .bash_history
by měl mít požadovaný výsledek. Subshell se spustí před .bash_history
je otevřen pro zápis. Jak je vysvětleno v odpovědi Phila P, v čase .bash_history
je načten v původním příkazu, byl již zkrácen pomocí >
operátor.
Řešení 2:
Doporučuji použít sponge
od moreutils. Z manuálové stránky:
DESCRIPTION
sponge reads standard input and writes it out to the specified file. Unlike
a shell redirect, sponge soaks up all its input before opening the output file.
This allows for constructing pipelines that read from and write to the same
file.
Chcete-li to použít na svůj problém, zkuste:
uniq .bash_history | sponge .bash_history
Řešení 3:
Problém je v tom, že váš shell nastavuje kanál příkazů před spuštěním příkazů. Nejde o „vstup a výstup“, jde o to, že obsah souboru je pryč ještě předtím, než uniq vůbec běží. Zní to nějak jako:
- Shell otevře
>
výstupní soubor pro zápis, jeho zkrácení - Shell se nastaví tak, aby pro tento výstup byl použit deskriptor souboru 1 (pro stdout)
- Shell spustí uniq, možná něco jako execlp("uniq", "uniq", ".bash_history", NULL)
- uniq běží, otevře .bash_history a nic tam nenajde
Existují různá řešení, včetně úprav na místě a použití dočasných souborů, o kterých se zmiňují jiní, ale klíčem je pochopit problém, co se vlastně děje a proč.
Řešení 4:
Další trik, jak to udělat, bez použití sponge
, je následující příkaz:
{ rm .bash_history && uniq > .bash_history; } < .bash_history
Toto je jeden z cheatů popsaných ve skvělém článku „In-place“ editace souborů na backreference.org.
V podstatě otevře soubor pro čtení a poté jej „odstraní“. Ve skutečnosti však není odstraněn:Je zde otevřený popisovač souboru, který na něj ukazuje, a dokud zůstane otevřený, soubor je stále k dispozici. Poté vytvoří nový soubor se stejným názvem a zapíše do něj jedinečné řádky.
Nevýhoda tohoto řešení:Pokud uniq
z nějakého důvodu selže, vaše historie bude pryč.
Řešení 5:
použijte houbu od moreutils
uniq .bash_history | sponge .bash_history