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.
Как вы обнаружили, это просто очищает содержимое файла (усекает файл ); это отличается от rm
, так как rm
фактически полностью удалит файл. Кроме того, :>file.txt
фактически создаст файл, если он еще не существует.
:
— это «команда ничего не делать», которая завершится успешно и не выдаст никаких результатов, так что это просто короткий метод очистки файла. В большинстве оболочек вы можете просто выполнить >file.txt
, чтобы получить тот же результат. Это также может быть немного быстрее, чем другие методы, такие как echo >file.txt
, поскольку echo
потенциально может быть внешней командой.
Кроме того, echo >file.txt
поместит пустую строку в file.txt
, где :>file.txt
сделает файл вообще пустым.
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 в индексном узле после усечения, но вам все равно придется писать его, если размер изменился.
Да, это отличается от rm
.
rm
удалит файл.
:>filename.txt
очищает файл, оставляя его на месте, но размером ноль байтов.
Вызов оболочки >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