Різниця між cat і '>' до нуля файлу


23

Чи відрізняються ці дві команди від того, як вони обходять нульові файли? Чи останній коротший спосіб зробити перший? Що відбувається за лаштунками?

І те й інше

$ cat /dev/null > file.txt

$ > file.txt 

урожайність

-rw-r--r--  1 user  wheel  0 May 18 10:33 file.txt

Відповіді:


28

cat /dev/null > file.txt- марне використання кота .

В основному cat /dev/nullпросто catнічого не виходить. Так, це працює, але багато хто знущається, оскільки це призводить до залучення зовнішнього процесу, який не є необхідним.
Це одна з тих речей, яка є загальною просто тому, що вона є загальною.

Використання просто > file.txtбуде працювати на більшості оболонок, але це не повністю портативно. Якщо ви хочете повністю портативні, такі хороші альтернативи:

true > file.txt
: > file.txt

Як :і trueвихід відсутня, а також оболонки вбудованих функцій ( в той час як catзовнішня корисність), таким чином , вони легше і більш «правильні».

 

Оновлення:

Як згадував tylerl у своєму коментарі, є і >| file.txtсинтаксис.

Більшість оболонок мають налаштування, які не дозволять їм обрізати існуючий файл через >. Ви повинні використовувати >|замість цього. Це запобігає помилкам людини, коли ви дійсно мали намір додати >>. Ви можете ввімкнути поведінку за допомогою set -C.

Отже, з цим, я думаю, найпростішим, найправильнішим і портативним методом обрізки файлу буде:

:>| file.txt

2
Команда двокрапки визначається в POSIX . Це нульова операція, що існує для розширення аргументів командного рядка.
kojiro

3
LOL, "зловживання котами"
КМ.

2
@kojiro :також зобов’язаний POSIX бути вбудованим, і він фактично відрізняється trueтим, що вважається "спеціальним" вбудованим .
jw013

2
не забувайте про noclobber . >| fileє більш чітким усіканням.
tylerl

1
Ніякого trueне потрібно вбудовувати, а традиційно цього не було. :побудований у всіх оболонках родини Борн. :є спеціальним вбудованим для POSIX (таким чином : > file, вийде з оболонки, наприклад, якщо fileне вдасться відкрити для запису в оболонки POSIX) і trueні. POSIX навіть згадує, що :може бути ефективнішим, ніж trueу деяких системах.
Стефан Шазелас

23

З точки зору портативності:

                      Bourne POSIX  zsh    csh/tcsh  rc/es  fish
> file                Y      Y      N(1)   N(1)      N      N
: > file              N/Y(2) Y(3)   Y      Y(4)      N(5)   N(5)
true > file           Y(5)   Y      Y      Y(5)      Y(5)   Y(5)
cat /dev/null > file  Y(5)   Y      Y(5)   Y(5)      Y(5)   Y(5)
eval > file           Y(3,8) Y(3)   Y      Y(6)      Y      Y
cp /dev/null file (7) Y(5)   Y      Y(5)   Y(5)      Y(5)   Y(5)
printf '' > file      Y(5)   Y      Y      Y(5)      Y(5)   Y

Примітки:

  1. окрім in shабо kshемуляції, для перенаправлень без команди, в zsh передбачається команда за замовчуванням (пейджер для перенаправлення stdin, в catіншому випадку), який може бути налаштований за допомогою змінних NULLCMD та READNULLCMD. Це натхненно подібною особливістю в(t)csh
  2. Перенаправлення спочатку не виконувались для :UnixV7, оскільки :інтерпретувались на півдорозі між лідером коментаря та нульовою командою. Пізніше вони були, як і для всіх вбудованих, якщо перенаправлення не вдалося, виходить із оболонки.
  3. :і evalбудучи спеціальними вбудованими, якщо перенаправлення не вдалося, виходить з оболонки ( bashце робиться лише в режимі POSIX).
  4. Цікаво, що в (t)csh, це визначає нульову мітку (для goto), тож goto ''там буде гілка. Якщо перенаправлення не вдалося, це закриває оболонку.
  5. Якщо / , якщо відповідна команда доступна в $PATH( як :правило , не є, true, cat, cpі як printfправило , не є (POSIX вимагає від них)).
  6. Якщо перенаправлення не вдалося, це закриває оболонку.
  7. Якщо fileє символьним посиланням на неіснуючий файл, однак деякі cpреалізації, такі як GNU, відмовляться його створювати.
  8. Початкові версії оболонки Борна не підтримували перенаправлення вбудованих файлів

З точки зору розбірливості:

(цей розділ є дуже суб'єктивним)

  • > file. Це >занадто схоже на запит або коментар. Також питання, яке я задаю, читаючи, що (і більшість оболонок буде скаржитися на те саме), який саме висновок ви перенаправляєте? .
  • : > file. :відома як команда no-op. Таким чином, це читається відразу як генерування порожнього файлу. Однак і тут знову це :можна легко пропустити та / або сприймати як підказку.
  • true > file: що стосується булевого перенаправлення або вмісту файлу? Що тут мається на увазі? це перше, що мені спадає на думку, коли я це читаю.
  • cat /dev/null > file. Об'єднатися /dev/nullв file? catякі часто бачили , як команда , щоб скинути вміст файлу, який все ще може мати сенс: скинути вміст в порожній файл вfile , трохи як згорнутої спосіб сказати , cp /dev/null fileале все - таки зрозуміло.
  • cp /dev/null file. Копіює вміст порожнього файлу в file. Має сенс, хоча хто - то , не знаючи , як cpце означало , щоб зробити за замовчуванням може подумати , що ви намагаєтеся зробити fileна nullпристрій , а також.
  • eval > fileабо eval '' > file. Нічого не працює і перенаправляє свій результат на a file. Має сенс для мене. Дивно, що це не звичайна ідіома.
  • printf '' > file: явно нічого не друкує у файл. Той, який має для мене найбільше сенсу.

З точки зору продуктивності

Різниця полягатиме в тому, використовуємо ми вбудовану оболонку чи ні. Якщо ні, процес повинен бути роздвоєним, команда завантажена та виконана.

evalгарантовано будується у всіх оболонках. :вбудований де завгодно (Bourne / csh like). trueпобудований лише у мурашниках Борна.

printfвбудований у більшість сучасних оболонок Борна і fish.

cpі, catяк правило, не вбудовані.

Тепер cp /dev/null fileне посилається на переадресацію оболонки, тому такі речі, як:

find . -exec cp /dev/null {} \;

будуть ефективнішими, ніж:

find . -exec sh -c '> "$1"' sh {} \;

(хоча не обов'язково, ніж:

find . -exec sh -c 'for f do : > "$f"; done' sh {} +

).

Особисто

Особисто я використовую : > fileв Борн-подібних снарядах, і не використовую нічого іншого, крім оболонок Борна в наші дні.


Про що dd of=file count=0?
kojiro

2
@kojiro, Деякі реалізації dd(як мінімум, Solaris 10-х) count=0ігноруються. dd if=/dev/null of=fileбуло б більш портативним. У будь-якому випадку, це незалежно від оболонки.
Стефан Шазелас

Гаразд, але це не менш заслуговує на включення, ніж cp /dev/null file, правда?
Кідро

2
@kojiro, cp /dev/null fileє загальною ідіомою. Я обмежуюсь цим, справа не в переліку всіх можливих способів.
Стефан Шазелас

5

Можливо, ви захочете подивитися truncate, що саме так: усікайте файл.

Наприклад:

truncate --size 0 file.txt

Це, мабуть, повільніше, ніж використання true > file.txt.

Однак моя головна думка: truncateпризначена для обрізання файлів, а використання> має побічний ефект обрізання файлу.


2
Округлення приємно , коли ви хочете , щоб обрізати файл на що - то інше , ніж 0. Тим НЕ менше, навіть без оболонки дивного твердження: ви можете описати контекст , в якому truncateбуде доступний, але ні >ні unistdбібліотеки C будуть доступні?
Кідро

Не зовсім. Напевно, є більш елегантне рішення для кожного доступного сценарію чи мови програмування.
Фабіан

3
truncate- це утиліта FreeBSD, відносно недавно (2008 р.) додана до ядер GNU (хоча --sizeстиль GNU довгих опцій є специфічним для GNU), тому він недоступний у системах, що не є GNU або FreeBSD, і не доступний у старих системах GNU, Я б не сказав, що це портативний. cp /dev/null fileпрацював би без перенаправлення оболонки і був би більш портативним.
Стефан Шазелас

Гаразд, я видалю коментар щодо портативності. Хоча ваше визначення останніх, здається, відрізняється.
Фабіан

2

Відповідь трохи залежить від того, що file.txtє, і як процес писати до нього!

Я наводжу поширений випадок використання: у вас зростає логфайл, який зростає file.txt, і ви хочете його обертати.

Тому ви копіюєте, наприклад, file.txtу file.txt.save, а потім усікаєте file.txt.

У цьому сценарії якщо файл не відкривається another_process(наприклад: це another_processможе бути програма, що виводить цей файл, наприклад, програма, яка щось реєструє), то ваші 2 пропозиції еквівалентні, і обидві працюють добре (але 2-й вважається кращим як перший "cat / dev / null> file.txt" - це марне використання кота, а також відкривається та читається / dev / null).

Але справжня проблема буде в тому випадку, якщо other_processфункція все ще активна і все ще має відкриту ручку, що переходить до file.txt.

Тоді виникають 2 основні випадки, залежно від того, як other process відкрили файл:

  • Якщо other_process відкрити його звичайним чином, то ручка все одно буде вказувати на колишнє місце у файлі, наприклад, на зміщення 1200 байт. Наступне записування, таким чином, розпочнеться зі зміщення 1200, і, таким чином, ви знову матимете файл 1200байтів (+ що б не написав other_process) зі 1200 провідними нульовими символами! Я припускаю, що не ви хочете .

  • Якщо його other_processвідкрити file.txtв "режимі додавання", то кожен раз, коли він пише, вказівник активно прагне до кінця файлу. Тому, коли ви вріжете його, він буде "шукати" до байта 0, і у вас не буде поганого побічного ефекту! Це те, що ти хочеш (... зазвичай!)

Зверніть увагу, що це означає, що вам потрібно, коли ви усікаєте файл, переконатися, що все other_process записи ще записуються до цього місця, відкрили його в режимі "додавання". Інакше вам потрібно буде зупинити їх other_processі запустити їх знову, щоб вони почали вказувати на початок файлу замість колишнього місця розташування.

Посилання: /programming//a/16720582/1841533 для отримання більш чіткого пояснення та прикладного короткого прикладу різниці між нормальним і додаванням журнального режиму за адресою /programming//a/984761/1841533


2
Дуже мало цієї відповіді насправді стосується або відповідає на питання. Різниця між a cat /dev/null > fileі a > file- це, cat /dev/nullі це не має значення для файлу.
jw013

@ jw013: Правда! Але я просто хотів скористатися можливістю питання, щоб повторно вказати інформацію про те, "що ти хочеш / не те, що ти хочеш", оскільки це не дуже добре відомо, і могло б сильно вдарити когось, хто намагається обертати журнали (звичайний випадок, коли ти хочеш усікають файл).
Олів’є Дулак

1
На все є час і місце. Ваша інформація може бути корисною в іншому контексті, але вона тут не належить - ви повинні знайти більш відповідне місце для неї, оскільки ніхто не намагається обертати журнали, не збирається розглянути це абсолютно не пов'язане питання про переадресацію. Тут ваша відповідь - еквівалент цифрового бур’яну, подібно до того, як інакше корисна рослина гарбуза посеред кукурудзяного поля вважатиметься бур’яном.
jw013

1

Мені це подобається і використовую його часто, тому що він виглядає чистіше, а не як хтось випадково потрапив до клавіші повернення:

echo -n "" > file.txt

Чи повинен бути вбудованим теж?


3
Існує багато способів зняти з нуля файл. Я думаю, що КМ. цікавило лише розуміння різниці між двома методами, показаними у питанні.
пр

6
Багато echoреалізацій не підтримують -n-n<SPC><NL>printf '' > file.txt
виходили
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.