Перенаправление IO и главная команда

Можно настроить привязки клавиш и установить много настроек для less в названном файле ~/.lesskey. После того как Вы создали файл, выполнение lesskey команда; это генерирует названный файл ~/.less который less чтения, когда это запускается.

Установка Вас хочет, LESSOPEN. Это - входное средство форматирования для меньше. less пакет идет с демонстрационным средством форматирования в /bin/lesspipe; это распаковывает gzipped файлы, выставочные списки содержания для многих многофайловых форматов архива, и преобразовывает несколько форматов форматированных текстов в простой текст. В Вашем ~/.lesskey:

#env
LESSOPEN=|/bin/lesspipe %s

9
30.06.2011, 01:07
6 ответов

Когда оболочка получает командную строку как: command > file.out сама оболочка открывается (и возможно создает), названный файл file.out. Оболочка устанавливает дескриптор файла 0 на дескриптор файла файла, который это получило от открытого. Это - то, как перенаправление ввода-вывода работает: каждый процесс знает о дескрипторах файлов 0, 1 и 2.

Твердая часть об этом - то, как открыться file.out. Большую часть времени Вы хотите file.out открытый для записи при смещении 0 (т.е. усеченный) и это - то, что оболочка сделала для Вас. Это усеченный .hgignore, открытый это для записи, dup'ed filedescriptor к 0, затем exec'ed head. Мгновенное избиение файла.

В оболочке удара Вы делаете a set noclobber изменить это поведение.

10
27.01.2020, 20:04
  • 1
    Ага, я вижу. Я действительно думал, что оболочка усекала файл прежде, чем выполнить команду, но я не знал почему. Спасибо за объяснение! –  voithos 29.06.2011, 23:18

Я думаю ответы Bruce, что продолжается здесь конвейер оболочки.

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

$ head -1 .hgignore | sponge .hgignore

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

$ head -1 .hgingore > .hgignore.tmp
$ mv .hgignore{.tmp,}
10
27.01.2020, 20:04
  • 1
    Смотря на это несколько лет спустя, мысль произошла со мной: не могли мы просто сделать head -1 .hgignore | tee .hgignore? tee находится в coreutils, и как привилегия/побочный эффект, это также пишет в STDOUT –  voithos 28.03.2014, 16:51
  • 2
    @voithos К моему знанию tee открывает и усекает файл, который это пишет в то, когда это инстанцируют точно так же, как все остальное так, что это не решает основной вопрос здесь состояния состязания при чтении содержания файла перед усечением его с записью. –  Caleb 28.03.2014, 19:37
  • 3
    Вы поднимаете точку, о которой я не знал, на самом деле - а именно, что переданные по каналу команды сразу запускаются, вместо последовательно. Это точно? Я действительно, однако, проверял его и tee кажется, делает желаемую вещь. У меня есть версия 8.13 на моей машине. –  voithos 28.03.2014, 19:47
  • 4
    @voithos Да, команды в pipline и всех включенных каналах ввода-вывода запускаются в обратном порядке так конвейер, готов получить данные, когда первый начинает давать его. Я подозреваю, что Ваш тест испорчен, потому что Вы, вероятно, использовали слишком маленький блок данных, и это кэшировало все это в буфере чтения перед необходимостью в нем. tee программа усечет Ваши файлы, это не установка к двойному буферу их. –  Caleb 29.03.2014, 13:32

Решение Настоящего Человека

ed .hgignore
$d
wq

или как острота

printf '%s\n' '$d' 'wq' | ed .hgignore

Или с GNU sed:

sed -i '$d' .hgignore

(Нет, я шучу. Я использовал бы интерактивного редактора. vi .hgignore GddZZ)

1
27.01.2020, 20:04
  • 1
    я задался вопросом, там любое преимущество для использования :wq ZZ? –  voithos 30.06.2011, 01:40
  • 2
    Кроме того, :x который является тем, что мои пальцы делают автоматически –  glenn jackman 30.06.2011, 03:04
  • 3
    и ZQ совпадает с :q! –  glenn jackman 30.06.2011, 03:05
  • 4
    ZZ и :x только запишите, существует ли что-то для записи...: w всегда fsyncs файл к диску независимо, если этому нужен он. Я использую: xa, потому что я использую вкладки. –  xenoterracide 10.07.2012, 12:37

Для оперативного файла, редактируя Вас может также использовать открытый прием дескриптора файла как показано Jürgen Hötzel в выводе Перенаправления от sed 's/c/d /' myFile к myFile.

exec 3<.hgignore
rm .hgignore  # prevent open file from being truncated
head -1 <&3 > .hgignore

ls -l .hgignore  # note that permissions may have changed
0
27.01.2020, 20:04
  • 1
    И сразу после rm .hgignore Ваши сбои питания, устраняя часы тяжелой работы. Хорошо, это не имеет значения для .hgignore, но почему Вы сделали бы что-то, что это усложнило так или иначе? Таким образом мой downvote: технически корректный, но очень плохая идея. –  Gilles 'SO- stop being evil' 30.06.2011, 23:57
  • 2
    @Gilles, возможно, не настолько хорошая идея, но это, например, что perl -i (для оперативного редактирования), делает, и я не был бы удивлен если некоторые реализации sed -i он также (хотя последняя версия GNU sed кажется не). –  Stéphane Chazelas 19.02.2013, 22:20

В

head -n 1 file > file

file является усеченным прежде head запускается, но если Вы пишете это:

head -n 1 file 1<> file

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

Однако после head возвратился и в то время как fd все еще открыто, можно назвать другую команду, которая делает truncate.

Например:

{ head -n 1 file; perl -e 'truncate STDOUT, tell STDOUT'; } 1<> file

Какие вопросы здесь это truncate выше, head просто перемещает курсор для fd 1 в файле сразу после первой строки. Это действительно переписывает первую строку, к которой мы не нуждались в нем, но это не вредно.

С головой POSIX мы могли на самом деле уйти, не переписывая ту первую строку:

{ head -n 1 > /dev/null
  perl -e 'truncate STDIN, tell STDIN'
} <> file

Здесь, мы используем факт это head перемещает позицию курсора в ее stdin. В то время как head обычно читал бы его вход большими блоками для улучшения производительности, POSIX потребует его (где возможный) к seek назад сразу после первой строки, если это пошло вне его. Обратите внимание однако, что не все реализации делают это.

С другой стороны, можно использовать оболочку read управляйте вместо этого в этом случае:

{ read -r dummy; perl -e 'truncate STDIN, tell STDIN'; } <> file
3
27.01.2020, 20:04
  • 1
    Stephane, Вы знаете о стандарте или команде coreutils, которая может усечь STDIN подобный тому, что Вы выполнили использование perl выше –  iruvar 27.08.2015, 17:11
  • 2
    @1_CR, нет. dd может усечь при любом произвольном абсолютном смещении в файле все же. Таким образом, можно определить байтовое смещение второй строки и усечь оттуда с dd bs=1 seek="$offset" of=file –  Stéphane Chazelas 27.08.2015, 17:36

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

ex -sc '2,d|x' .hgignore
  1. 2, выберите строки 2 до конца

  2. d удалить

  3. x сохранить и закрыть

1
27.01.2020, 20:04

Теги

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