Что делает :>filename.txt?

cat /etc/issue

дал мнеDebian GNU/Linux 9 \n \l

Итак, я заменил старую конфигурацию пакета wheezyв файле sources.list; изменил их наstretch:

deb http://deb.debian.org/debian stretch main contrib non-free
deb-src http://deb.debian.org/debian stretch main contrib non-free

deb http://deb.debian.org/debian stretch-updates main contrib non-free
deb-src http://deb.debian.org/debian stretch-updates main contrib non-free

deb http://security.debian.org/debian-security/ stretch/updates main contrib non-free
deb-src http://security.debian.org/debian-security/ stretch/updates main contrib non-free

К сожалению, пакеты, кажется, были на wheezy и теперь обновлены через jessie до stretch.

23
15.11.2019, 21:44
4 ответа

Как вы обнаружили, это просто очищает содержимое файла (усекает файл ); это отличается от rm, так как rmфактически полностью удалит файл. Кроме того, :>file.txtфактически создаст файл, если он еще не существует.

:— это «команда ничего не делать», которая завершится успешно и не выдаст никаких результатов, так что это просто короткий метод очистки файла. В большинстве оболочек вы можете просто выполнить >file.txt, чтобы получить тот же результат. Это также может быть немного быстрее, чем другие методы, такие как echo >file.txt, поскольку echoпотенциально может быть внешней командой.

Кроме того, echo >file.txtпоместит пустую строку в file.txt, где :>file.txtсделает файл вообще пустым.

38
27.01.2020, 19:41

re :производительность :в оболочке это максимально эффективно; простое обращение к ядру с просьбой обрезать существующий файл должно быть более эффективным, чем удаление файла и повторное -создание нового inode с тем же именем. Если вы не хотите удалить файл, в этом случае rmили unlinkего.

:— это оболочка, встроенная -, поэтому она избегает fork/exec. То же самое и с эквивалентом trueв нормальных современных оболочках.

>fooили true > fooзаставляет оболочку обрезать файл, создавая
open(path, O_WRONLY|O_TRUNC|O_CREAT, 0666)системный вызов.

Или на практике с DASH в Linux из вывода strace sh:
openat(AT_FDCWD, "foo", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3что эквивалентно.

Тогда он должен снова close()этот FD. На самом деле DASH не делает этого в особом случае, когда вы используете :>, он проходит через следующие обручи:

openat(AT_FDCWD, "foo", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 10          # save original stdout
fcntl(1, F_GETFD)                       = 0
fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
dup2(3, 1)                              = 1           # redirect stdout to foo
close(3)                                = 0           # then close 3
dup2(10, 1)                             = 1           # then restore original stdout
fcntl(10, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
close(10)                               = 0

Использование > fooв DASH приводит к той же последовательности системных вызовов, фактически перенаправляя fd1 и затем восстанавливая его. Я не проверял bashили другие оболочки.

Но это все же значительно дешевле, чем создание нового процесса для запуска truncate -s 0 foo, который (надеюсь, )сделает одинtruncate("foo", 0)системный вызов , что, по-видимому, даже более эффективно, чем open+ close.

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

В Dash 3>fooприводит к этой последовательности системных вызовов:

openat(AT_FDCWD, "foo", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
close(3)                                = 0

Открытие нового fd приводит к тому, что оно уже является fd 3, что позволяет избежать дублирования.Это самый эффективный способ в dash, вероятно, экономящий несколько микросекунд по сравнению с >foo. Если это имеет значение, язык сценариев оболочки не подходит для вашей задачи! Но ты спросил.


При включенном смягчении последствий Spectre+Meltdown даже -ENOSYSнекорректный системный вызов занимает не менее тысяч тактов, то есть микросекунд, на современных процессорах Intel x86 -64. По сравнению с парой сотен для пользователя -> ядро ​​-> пользовательский круговой обход только с инструкцией syscall. Конечно, поиск путей и т. д. занимает значительное время, как и код файловой системы. И переход в режим ядра и обратно часто вытесняет часть кеша, из-за чего пользовательское -пространство работает медленнее по возвращении.

Фактическая стоимость операций ввода-вывода после записи метаданных -обратно на диск зависит от файловой системы. FS, такие как XFS или современные ext4, использующие только 1 или несколько больших экстентов для всего файла, могут легко освободить огромное количество места за время O (1 ). Или O (n ), где n— количество экстентов (фрагментация ), а не размер в байтах.

В зависимости от FS, если информация об экстенте хранилась прямо в индексном узле, а не в непрямом блоке, то в список свободных нужно добавить на одну вещь меньше.

Затраты на ввод-вывод аналогичны отмене связи с файлом, но вам не нужно освобождать индексный дескриптор или изменять запись в каталоге. Вам все равно придется обновлять mtime и ctime в индексном узле после усечения, но вам все равно придется писать его, если размер изменился.

2
27.01.2020, 19:41

Да, это отличается от rm.

rmудалит файл.

:>filename.txtочищает файл, оставляя его на месте, но размером ноль байтов.

8
27.01.2020, 19:41

Вызов оболочки >filename.txtперенаправляет часть вывода в файл "filename.txt", чтобы полностью заменить его. Таким образом, оболочка должна очистить все содержимое данного файла перед записью в него вывода.

Перенаправляемый вывод — это вывод выполненной команды. Нравится:

$ echo Hello >filename.txt

Файл с именем filename.txt будет содержать ровно (и только )строку Hello.

Выполнение:

$ echo "New Value" >filename.txt
$ cat filename.txt
New Value

сотрет все внутри файла, а затем запишет в него New Value.

Если у команды нет выходных данных, как у команды true, файл останется пустым (усеченным ).

$ true >filename.txt
$ cat filename.txt

Команда, которая также является встроенной в оболочку, представляет собой:(просто двойную точку (двоеточие ))и не имеет вывода. Будучи встроенной, она работает быстрее, чем внешняя команда, такая как true(, которая также не имеет вывода ). Итак, либо:

$ :  >  filename.txt
$ :  >filename.txt
$ :>filename.txt

удалит все содержимое из файла с именем filename.txtили создаст его как пустой файл, если он не существует.

Is this different from an rm?

Это отличается от rm, так как rm приведет к исчезновению файла из ls, а не к тому, что файл будет содержать 0 байтов.

Does it operate faster or slower than other similar means of zeroing a file or deleting it?

Опять же, файл не удаляется (исчезает из списка, заданногоls)он превращается в пустой файл (содержит 0 байт ).

Это должно быть быстрее, чем вызов внешней команды для очистки файла. Необходимость создать дочернюю оболочку для загрузки исполняемого файла и execделает внешние команды медленнее, чем встроенные :.

Аналогичные решения: (некоторое множество $?равное 1):

[ ]         > filename.txt
builtin     > filename.txt
command     > filename.txt
printf ''   > filename.txt
4
27.01.2020, 19:41

Теги

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