Я просто запустил следующее в bash:
uniq .bash_history > .bash_history
и мой файл истории оказался совершенно пустым.
Я думаю, мне нужен способ прочитать весь файл перед записью в него. Как это сделать?
PS: Я, очевидно, думал об использовании временного файла, но я ищу более элегантное решение.
bash
не будет помещать последовательные дубликаты в свою историю, если вы установите HISTCONTROL для включения ignoredups; см. справочную страницу.Ответы:
Я рекомендую использовать
sponge
от moreutils . Из справочной страницы:Чтобы применить это к вашей проблеме, попробуйте:
источник
Я просто хотел представить другой ответ, который прост и не использует губку (потому что он часто не включается в облегченные среды).
должен иметь желаемый результат. Подоболочка исполняется до того, как .bash_history открывается для записи. Как объясняется в ответе Фила П, к тому моменту, когда .bash_history прочитан в исходной команде, он уже был обрезан оператором>.
источник
$()
вместо кавычек из-за некоторых проблем с выходом из строя.echo "$(fmt -p '# ' -w 50 readme.txt)" > readme.txt
сегодня. Долго искал вокруг элегантное решение. Большое спасибо, @Hart Simha!Проблема в том, что ваша оболочка настраивает конвейер команд перед запуском команд. Дело не в «вводе и выводе», а в том, что содержимое файла уже удалено до того, как uniq даже запустится. Это выглядит примерно так:
>
выходной файл для записи, обрезая егоСуществуют различные решения, в том числе редактирование на месте и использование временного файла, о котором упоминают другие, но главное - понять проблему, что на самом деле идет не так и почему.
источник
Еще один трюк, чтобы сделать это без использования
sponge
, это следующая команда:Это один из читов, описанных в отличной статье «Редактирование файлов на месте» на backreference.org.
Он в основном открывает файл для чтения, затем «удаляет» его. Однако на самом деле он не удален: на него указывает дескриптор открытого файла, и пока он остается открытым, файл все еще существует. Затем он создает новый файл с тем же именем и записывает в него уникальные строки.
Недостаток этого решения: если
uniq
по какой-то причине произойдет сбой, ваша история исчезнет.источник
использовать губку от moreutils
источник
Этот
sed
скрипт удаляет соседние дубликаты. С-i
опцией, он делает модификацию на месте. Это изsed
info
файла:источник
strace
иллюстрацией (не то, чтобы это действительно имело значение) :-)process input > tmp && mv tmp input
гораздо проще и более читабельно, чем использованиеsed
хитрости просто для того, чтобы избежать временного файла, и он не будет перезаписывать мой оригинал, если он потерпит неудачу (я не знаю, будет лиsed -i
неудача изящной - я хотел бы думаю, что будет, хотя). Кроме того, есть много вещей, которые вы можете сделать с помощью метода output-to-temp-file, который нельзя сделать на месте без чего-то более сложного, чем этотsed
скрипт. Я знаю, что вы знаете все это, но это может принести пользу некоторым зрителям.Как интересный трюк, sed также использует временный файл (это только для вас):
Описание:
временный файл
./sedPmPv9z
становится Fd 4, иfoo
файлы становятся Fd 3. Операций чтения на дескрипторе 3, и запись на Fd 4 (временный файл). Затем файл foo перезаписывается временным файлом в вызове переименования.источник
Другое решение:
источник
Временный файл - это почти то же самое, если только рассматриваемая команда не поддерживает редактирование на месте (
uniq
нет - некоторыеsed
делают do (sed -i
)).источник
Вы можете использовать Vim в режиме Ex:
%
выбрать все строки!
Команда Runx
сохранить и закрытьисточник
Вы также можете использовать tee, используя вывод uniq в качестве входных данных:
источник