Что-то я чувствую, что должен знать наверняка: если я ls <something>
, будет rm <something>
удалите точно те же файлы это ls
отображенный? Есть ли любые обстоятельства где rm
мог удалить файлы это ls
не показал? (Это находится в этих 18,04 ударах),
Править: спасибо всем, кто ответил. Я думаю, что полный ответ является комбинацией всех ответов, таким образом, я принял наиболее проголосовавший ответ как "ответ".
Неожиданные вещи я учился по пути:
ls
не так просто, как Вы могли бы думать в его обработке его аргументовls
Ну, оба ls
и rm
воздействуйте на аргументы, которые передаются им.
Этими аргументами может быть простой файл, таким образом, ls file.ext
и rm file.ext
воздействуйте на тот же файл, и результат ясен (перечислите файл / удаляют файл).
Если вместо этого аргументом является каталог, ls directory
перечисляет содержание каталога в то время как rm directory
не будет работать, как (т.е. rm
без флагов не может удалить каталоги, в то время как, если Вы делаете rm -r directory
, это рекурсивно удаляет все файлы под directory
и сам каталог).
Но имейте в виду, что параметры командной строки могут быть подвергнуты для окружения расширения, таким образом, не всегда гарантируется, что те же аргументы передаются обеим командам, если они содержат подстановочные знаки, переменные, произведенные от других команд, и т.д.
Как экстремальный пример думают ls $(rand).txt
и rm $(rand).txt
, аргументами является "то же", но результаты очень отличаются!
Как насчет:
$ mkdir what
$ cd what
$ mkdir -p huh/uhm ./-r
$ ls *
uhm
$ rm *
$ ls
-r
$ ls -R
.:
-r
./-r:
В основном подстановочные знаки, расширяющиеся до элементов, начинающихся с -
(или вводимых вручную элементов, начинающихся с -
, но это выглядит как обман), могут интерпретироваться по-разному [ 113] и rm
.
Если вы сделаете только ls
вместо ls -a
, да rm
может удалить скрытые файлы, которые вы не видели с ls
без -a
.
Пример:
Согласно:
dir_test
├── .test
└── test2
ls dir_test
: будет отображаться только test2
ls -A dir_test
: будет отображаться test2 + .test
rm -r dir_test
: удалит все (.test + test2)
Я надеюсь, что это поможет вам.
Если Вы думаете о чем-то как ls foo*.txt
по сравнению с. rm foo*.txt
, затем да, они покажут и удалят те же файлы. Оболочка разворачивает шарик и передает его рассматриваемой команде, и работа команд над перечисленными файлами. Один список их, одно удаление их.
Заметное отличие - это, если какой-либо из тех файлов, оказалось, был каталогом, то ls
перечислил бы его содержание, но rm
не удался бы удалить его. Это - обычно не проблема с тех пор rm
удалил бы меньше, чем, чем показали ls
.
Большая проблема здесь прибывает из выполнения ls *
или rm *
в каталоге, содержащем имена файлов, запускающиеся с тире. Они расширились бы до командных строк двух программ, как будто Вы записали им сами, и ls
взял бы -r
означать "обратный порядок сортировки", в то время как rm
взял бы -r
означать рекурсивное удаление. Различие имеет значение, есть ли у Вас подкаталоги по крайней мере два уровня глубоко. (ls *
покажет содержание первых каталогов уровня, но rm -r *
будет все мимо первого подуровня, также.)
Чтобы избежать что, запишите разрешающие шарики с продвижением ./
указать на текущий каталог и/или поместить a --
сигнализировать о конце опции, обрабатывающей перед шариком (т.е. rm ./*
или rm -- *
).
С шариком как *.txt
, это - на самом деле не проблема, так как точка является недопустимым символом опции и вызовет ошибку (пока кто-то не разворачивает утилиты для изобретения значения для нее), но еще более безопасно поместить ./
там так или иначе.
Конечно, Вы могли также получить различные результаты для двух команд, если бы Вы изменили globbing опции оболочки или создали/переместили/удалили файлы, промежуточные команды, но я сомневаюсь, что Вы имели в виду любой из тех случаев. (Контакт с новыми/перемещенными файлами был бы чрезвычайно грязен, чтобы сделать безопасно.)
Если Вы вводите ls *
и затем rm *
, возможно, что Вы удалите больше файлов, чем ls
показал - они, возможно, были созданы в крошечном временном интервале между концом ls
и запустите rm
.
При не принятии во внимание поведения оболочки давайте сфокусируемся на только что rm
и ls
может иметь дело с собой. По крайней мере один случай, где ls
покажет что rm
не может удалить включает полномочия каталога и другой - специальные каталоги .
и ..
.
rm
операция на каталоге, потому что путем удаления файла, Вы изменяете содержание каталога (или другими словами перечисляете записей каталога, так как каталог является не чем иным как списком имен файлов и inodes). Это означает, что Вы должны записать полномочия на каталоге. Даже если Вы - владелец файла без полномочий каталога, Вы не можете удалить файлы. Реверс также верен: rm
может удалить файлы, которые могут принадлежать другим, если Вы - владелец каталога.
Таким образом, Вы, возможно, прочитали и выполняете полномочия на каталоге, который позволит Вам, пересекают каталог и просматривают содержание в очень хорошо, например ls /bin/echo
, но Вы не можете rm /bin/echo
если Вы не владелец /bin
или поднимите свои полномочия с sudo
.
И Вы будете видеть случаи как это везде. Вот один такой случай: https://superuser.com/a/331124/418028
Другой особый случай .
и ..
каталоги. Если Вы делаете ls .
или ls ..
, это счастливо покажет Вам содержание, но rm
'луг их не позволяется:
$ rm -rf .
rm: refusing to remove '.' or '..' directory: skipping '.'
ls *
и rm *
не ответственны за расширение шарика - это сделано оболочкой прежде, чем передать его команде.
Это означает, что можно использовать любую команду с расширенным списком файлов - таким образом, я использовал бы что-то, что делает как можно меньше.
Так лучший способ сделать это (или по крайней мере, иначе) должно пропустить посредника.
echo *
покажет Вам точно, что было бы передано Вашему rm
команда.
Существуют пограничные случаи где что ls
шоу не что rm
удаляет. Скорее экстремальное значение, но к счастью мягкое - то, если аргументом, который Вы передаете, является символьная ссылка на каталог: ls
покажет Вам все файлы в symlinked каталоге, в то время как rm
удалит символьную ссылку, оставляя исходный каталог и его содержание нетронутыми:
% ln -s $HOME some_link
% ls some_link # Will display directory contents
bin lib Desktop ...
% rm some_link
% ls $HOME
bin lib Desktop ...
Уже существует много хороших ответов, но я хочу добавить некоторое более глубокое понимание.
Задайте себе вопрос: Скольким передаются параметры ls
, если Вы пишете
ls *
...? Обратите внимание что ls
команда не добирается *
как параметр, если существуют какие-либо файлы это *
может быть расширен до. Вместо этого оболочка сначала выполняет globbing прежде, чем вызвать команду, таким образом, ls
команда на самом деле получает столько же параметров, сколько существуют файлы, подобранные globbing. Для подавления globbing заключите параметр в кавычки.
Это верно для любой команды: echo *
по сравнению с echo '*'
.
Существует сценарий, назовите его countparams.sh
протестировать эффект. Это говорит Вам, сколько параметров это было передано и перечисляет их.
#!/bin/bash
echo "This script was given $# parameters."
arr=( "$@" )
for ((i=0;i<$#;i++)); do
echo "Parameter $((i+1)): ${arr[$i]}"
done
Сделайте это исполняемым файлом и работайте ./countparams.sh *
. Извлеките уроки из его вывода!
Шарик развернет тот же путь оба раза, если содержание каталога будет тем же в те два различных времени.
Если Вы действительно хотите проверить то, что будет удалено, использовать rm -i *.txt
. Это предложит Вам отдельно каждый файл, прежде чем (пробующий к) удалят его.
Это, как гарантируют, будет безопасно против условий состязания:
ls *.txt
/ новый файл создается / rm *.txt
потому что Вам предлагает каждый файл та же программа, это делает удаление.
Это является слишком громоздким для нормальной эксплуатации, и если Вы искажаете rm
кому: rm -i
, Вы будете использовать \rm
или rm -f
справедливо часто. Но стоит, по крайней мере, упомянуть, что существует решение состояния состязания. (Это даже портативно к системам не-GNU: POSIX rm(1)
указывает -i
опция.)
Другая опция была бы массивом удара: to_remove=(*.txt)
, затем попросите, чтобы пользователь подтвердил (возможно, после выполнения ls -ld -- "${to_remove[@]}"
), затем rm -- "${to_remove[@]}"
. Таким образом, расширение шарика только сделано однажды, и список передается дословно rm
.
Другой практически применимой опцией является GNU rm -I
(страница справочника), которая запрашивает при удалении больше чем 4 объектов. (Но не показывает Вам список, просто общее количество.) Я использую alias rm='rm -I'
на моем рабочем столе.
Это - хорошая гарантия против перебирающего жир возврата с полувведенным шаблоном, который соответствует слишком много. Но использование ls
сначала обычно хорошо в каталоге, которым Вы владеете, или в однопользовательской системе, и когда нет фоновых процессов, которые могли асинхронно создать новые файлы там. Для принятия мер против перебирающего жир не вводить rm -rf /foo/bar/baz
слева направо. rm -rf /
является специальным в корпусе, но rm -rf /usr
не! Не учитывают -rf
часть, или запускаются с ls
, и только добавьте rm -rf
часть после ввода пути.