Чтение и запись файла: команда tee

Хорошо известно, что такая команда:

cat filename | some_sed_command >filename

стирает имя файла, так как перенаправление вывода, выполняемое перед командой, вызывает усечение имени файла.

Можно решить проблему следующим образом:

cat file | some_sed_command | tee file >/dev/null

, но я не уверен, что это сработает в любом случае: что произойдет, если файл (и результат команды sed) очень большой? Как операционная система может избежать перезаписи содержимого, которое до сих пор не прочитано? Я вижу, что есть также команда губки, которая должна работать в любом случае: она "безопаснее", чем тройник?

10
задан 31 March 2016 в 12:18

4 ответа

можно было решить проблему следующим образом:

cat file | some_sed_command | tee file >/dev/null

Никакой .

возможности file будут усеченным отбрасыванием, но нет никакой гарантии cat file | some_sed_command | tee file >/dev/null, не усечет file.

Все это зависит, на котором команда обрабатывается сначала, как в противоположность тому, что можно ожидать, , команды в канале не обрабатываются слева направо . Нет никакой гарантии, о которой команда будет выбрана сначала, таким образом, можно было бы также просто думать о ней, как случайным образом выбрано, и никогда не полагаются на оболочку, не выбирающую нарушающую.

Начиная с возможностей для незаконной команды, которая будет выбрана сначала, промежуточные три команды ниже, чем возможности для незаконной команды, которая будет выбрана сначала промежуточные две команды, менее вероятно, что file будет усеченным, но она все еще собирается произойти .

script.sh:

#!/bin/bash
for ((i=0; i<100; i++)); do
    cat >file <<-EOF
    foo
    bar
    EOF
    cat file |
        sed 's/bar/baz/' |
        tee file >/dev/null
    [ -s file ] &&
        echo 'Not truncated' ||
        echo 'Truncated'
done |
    sort |
    uniq -c
rm file
% bash script.sh
 93 Not truncated
  7 Truncated
% bash script.sh
 98 Not truncated
  2 Truncated
% bash script.sh
100 Not truncated

Так никогда использование что-то как cat file | some_sed_command | tee file >/dev/null. Используйте sponge в качестве предложенного Oli.

Как альтернатива, для thighter сред и / или относительно маленькие файлы можно использовать здесь строка и замена команды для чтения файла, прежде чем любая команда будет выполнена:

$ cat file
foo
bar
$ for ((i=0; i<100; i++)); do <<<"$(<file)" sed 's/bar/baz/' >file; done
$ cat file
foo
baz
0
ответ дан 31 March 2016 в 22:18
  • 1
    возможно, чувствительный к регистру.. попробуйте EFI/BOOT/bootx64.efi. Я также видел, что некоторые системы требуют, чтобы раздел восстановления был первым. небольшой ntfs раздел, отмеченный как зарезервированная система или восстановление – ravery 8 August 2017 в 08:22

Можно использовать Vim в режиме Ex:

ex -sc '%!some_sed_command' -cx filename
  1. % выбор все строки

  2. ! Команда выполнения

  3. x Сохраняет и вышла

0
ответ дан 31 March 2016 в 22:18
  • 1
    Вся потребность Acer иметь последний UEFI от Acer и затем установить " trust" для загрузочных файлов UEFI. Acer Aspire E15 не будет двойная загрузка, много настроек Trust деталей на шаге 35 askubuntu.com/questions/627416/… & Acer Very последние работы UEFI/BIOS, снижение, не требуемое, если никакое доверие не экранирует, необходимо теперь обновить: ubuntuforums.org/… – oldfred 13 December 2018 в 06:54

Для sed а именно, можно использовать -i оперативный аргумент. Это просто сохраняет назад в файл, который это открыло, например:

sed -i 's/ /-/g' filename

, Если Вы хотите сделать что-то более раскормленное, предполагая выполнение больше чем sed, да, можно буферизовать все это с sponge (от moreutils пакет), который "впитает" весь stdin перед выписыванием в файл. Это похоже tee, но с меньшей функциональностью. Для основного использования, хотя, это - в значительной степени общедоступная замена:

cat file | some_sed_command | sponge file >/dev/null

то, что более безопасен? Определенно. Это, вероятно, имеет пределы через поэтому, если Вы делаете что-то колоссальное (и не может оперативное редактирование с sed), Вы могли бы хотеть сделать свои редактирования во второй файл и затем mv что файл назад к исходному имени файла. Это должно быть атомарным (таким образом, что-либо в зависимости от этих файлов не повредится, если им будет нужен постоянный доступ).

0
ответ дан 31 March 2016 в 22:18
  • 1
    Попробованный оба, тем не менее ничто все же. – stilllearning 8 August 2017 в 08:40

О, но sponge не единственная опция; Вы не должны получать moreutils, чтобы заставить это работать правильно. Любой механизм будет работать, пока он удовлетворяет следующие два требования:

  1. Это принимает название выходного файла в качестве параметра.
  2. Это только создает выходной файл, после того как весь вход был обработан.

Вы видите, известная проблема, к которой относится OP, состоит в том, что оболочка создаст все файлы, которые необходимы, чтобы каналы работали перед ровным началом выполнить команды в конвейере, таким образом, это - оболочка, которая на самом деле усекает выходной файл (который, к сожалению, является также входным файлом), прежде чем любая из команд даже имела шанс начать выполняться.

Эти tee команда не работает, даже при том, что она удовлетворяет первое требование, потому что она не удовлетворяет второе требование: это будет всегда создавать выходной файл непосредственно после запуска, таким образом, это по существу настолько же плохо как создаст канал прямо в выходной файл. (Это на самом деле хуже, потому что его использование представляет недетерминированную случайную задержку, прежде чем выходной файл станет усеченным, таким образом, Вы могли бы думать, что это работает, в то время как на самом деле это не делает.)

Так, все нам нужно для решения этой проблемы, некоторая команда, которая буферизует весь ее вход прежде, чем произвести любой вывод, и это способно к принятию выходного имени файла в качестве параметра, так, чтобы мы не передавали его вывод по каналу в выходной файл. Одна такая команда shuf. Так, следующее выполнит то же самое, которое sponge делает:

    shuf --output=file --random-source=/dev/zero 

--random-source=/dev/zero приемы части shuf в выполнение ее вещи, не делая никакой перестановки вообще, таким образом, это буферизует Ваш вход, не изменяя его.

0
ответ дан 17 April 2019 в 06:19
  • 1
    Почему делает echo $$, возвращают различное число? – NerdOfLinux 7 August 2017 в 20:11

Другие вопросы по тегам:

Похожие вопросы: