Це спочатку дивовижна поведінка підстановки, оскільки в описі *
символу підстановки зазначено:
Відповідає будь-якому рядку, включаючи нульовий рядок.
... поки ви не зрозумієте, що період є трохи особливим, коли це перший символ імені файлу. Вступний текст у 3.5.8 Filename Expansion
ньому говорить:
Коли шаблон використовується для розширення імені файлу, символ '.' на початку імені файлу або одразу після косої риски слід чітко відповідати, якщо не встановлено параметр оболонки dotglob.
Як зауважив steeldriver, "шаблон використання" префіксації макетів за допомогою ./
корисний для обробки імен з провідними тире в оболонці bash . Це не впливає на розширення підстановки / назви файлів, але робить його більш безпечним / легшим в обробленні імен файлів, коли ви посилаєтесь на них, якщо вони починаються з символів, які ці програми можуть неправильно трактувати як параметри. Наприклад:
# I want a file named `-n`
$ touch -n
touch: invalid option -- 'n'
Try 'touch --help' for more information.
$ touch -- -n
### ok
$ touch ./-n
### ok
... і тепер, коли у мене є файл з іменем -n
, якщо мені трапиться цикл на нього за допомогою майна:
for file in *n
do
echo "$file"
done
... Я не отримую результатів!
Але якщо я префікс підстановочні з ./
,
for file in ./*n
do
echo "$file"
done
./-n
... Я бачу ім'я файлу.
Це простий приклад для демонстраційних цілей; див. Чому printf кращий за відлуння? з цієї причини та ін. Інші утиліти отримають інші параметри, тому краще представити назви комунальних послуг максимально безпечно. Якщо ви не префіксуєте підстановку для "втечі" імені файлів, вам доведеться "захищати" свої утиліти іншими способами; одне поширене - сигналізувати про закінчення варіантів --
, наприклад:
for file in *n
do
mv -- "$file" backup/"$file"
done
... який надійно передасть -n
ім'я файлу mv
(як видно з set -x
):
mv -- -n backup/-n
./*
полягає в тому, що він забезпечує, що імена, що починаються з-
, не трактуються як варіанти.