Не допускається пробіл у імені файлу?


31

Кажуть, що в Unix та Linux взагалі слід уникати пробілів у назві файлу (звичайний файл, dir, посилання, файл пристрою, ...).

Але я роблю це постійно. Для імені файлу з пробілом всередині,

  • У Наутілуса символ пробілу відображається як пробіл.
  • У терміналі Bash я або використовую \ для представлення пробілу, або додаю ім'я файлу до пари подвійних лапок.
  • у файлах деяких додатків (Nautilus, не впевнений, чи ОС це зробить), ім'я файлу записується з пробілом, заміненим на %20.

Невже пропуск у назві файлу не дозволений?

Як правильно використовувати чи обробляти пробіл у імені файлу правильно?


17
Це дозволено, але це дійсно, дуже дратує. Причин для цього немає. Не робіть цього.
Легкі перегони з Монікою

3
Ви також можете створити файли з назвою -rf ~(використання touch -- "-rf ~"), але я б не рекомендував це.
Ян Д. Скотт

5
Ви можете це зробити, це дозволено, як створити сценарій саморуйнування під назвою "cd", але ви не повинні цього робити. Ваш файл вже виглядає по-різному в трьох різних інструментах, чи не так це погано?
Falco

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

2
@snailboat Spaces - симптом реальної проблеми, яка є відсутністю стандартизації. Файлові системи Unix дозволяють "імена" файлів майже необмеженим бінарним краплі. Єдиними незаконними байтами є 0 і 47 ( /роздільник). Використання всіх 254 байтів, що залишилися, відкриває двері для всіх манер невимовного "імені". Очевидно, це божевільно, але не всі згодні з тим, що таке «розумне», і різні персонажі будуть ламати різні інструменти. Перетин розуму всіх досить невеликий .
jw013

Відповіді:


48

Пробіли, і справді кожен символ, окрім /NUL, дозволені у іменах. Рекомендація не використовувати пробіли у назви файлів походить від небезпеки того, що вони можуть бути неправильно інтерпретовані програмним забезпеченням, яке погано їх підтримує. Можливо, таке програмне забезпечення є баггі. Але також, можливо, мови програмування, такі як сценарій оболонки, занадто просто створюють програмне забезпечення, яке ламається, коли вони представлені назви файлів з пробілами, і ці помилки, як правило, проскакують через те, що сценарії оболонок не часто перевіряються їх розробниками, використовуючи назви файлів з пробілами в їх.

Проміжки, замінені на %20, не часто зустрічаються у назви файлів. В основному використовується для (веб) URL-адрес. Хоча це правда, що% -кодування з URL-адрес іноді потрапляє у назви файлів, часто випадково.


6
Це "кодування URL-адрес" або "відсоткове кодування" en.wikipedia.org/wiki/URL_encoding Відповідно до цього, найбільш підходящим ім'ям, мабуть, є "кодування URI", але люди знаходять URL-адресу простіше сказати, ніж URI , тому це поширена форма неправильне значення. Зауважте, набір зарезервованих символів у URI більше, ніж є для * nix імен файлів.
goldilocks

1
@Tim Я не знаю, що ви можете вказати символ NUL в будь-якому аргументі командного рядка в bash. Я спробував кілька речей, таких як цитування його за допомогою Ctrl-V і щось подібне, $(echo -e \\0)але це не вийшло. Справа в тому, що причина NUL не може бути використана в іменах файлів в тому, що вона не може бути використана в рядках C (адже це термінальний рядок), і всі основні API, а також практично всі рядки, якими обробляють програми C, використовують цей формат . Оскільки bashнаписано на C, воно може просто не підтримувати жодних рядків з NUL в них. Я можу помилятися, може бути якийсь незрозумілий спосіб ...
Селада,

1
Сортування залежить від контексту. Функції рядків, як правило, не враховують остаточний нуль (вірніше, перший нуль - це кінець рядка, навіть якщо після нього є речі), тому в цьому сенсі він має нульову довжину і тому вважатиметься порожнім.
goldilocks

3
@Celada, звичайно, ти можеш використовувати NULі башти, потрібно $'\0'. Наприклад:find . -print0 | while read -d $'\0' f; do echo "$f"; done
terdon

1
@goldilocks Чи насправді люди вимовляють URL як "url", грубо римуючи з "Earl"?
Майлз Рут

17

Простору будуть дозволені в іменах файлів, як ви помітили.

Якщо ви подивитесь на запис "більшості файлових систем UNIX" у цій графіці у вікіпедії , ви помітите:

  • Дозволяється будь-який 8-бітний набір символів. Під цим парасолькою ми можемо також передбачити 7-бітний ASCII, оскільки це підмножина різних 8-бітових наборів і завжди реалізується за допомогою 8-бітних байтів.

  • Єдиними забороненими символами є /і "null". "Null" посилається на нульовий байт, однак це не дозволяється в текстових даних.

Однак якщо ви скористаєтесь оболонкою, ви можете зрозуміти, що є деякі символи, які створюватимуть клопоту, головне *- оператор глобалізації POSIX.

Залежно від того, як ви хочете визначити "клопоту", ви можете включити туди пробіл (пробіли, вкладки, нові рядки тощо), оскільки це створює необхідність цитування "". Але це неминуче, оскільки пробіли дозволені, тому ...

Як правильно використовувати чи обробляти пробіл у імені файлу правильно?

У контексті оболонки / командного рядка оберніть ім’я файлу в одинарні чи подвійні лапки (але зауважте, що вони не є іншими WRT проблемами) або уникайте пробілів \, наприклад:

> foo my\ file\ with\ spaces\ in\ the\ name

1
Як вказати символ NUL в басі? Я хочу перевірити його на ім'я файлу.
Тім

1
Ви не можете. "Семантика execve" посилається на те, що в тексті C (та будь-якій іншій моїй моїй моїй мові мені відомості) текстові рядки закінчуються недійсними. Оболонка реалізована в C. Найнижча річ, яку я міг би придумати, touch $(echo -e "foo\00bar")- це -eобробка \0Nяк вісімкове значення, але вона все ще десь губиться, оскільки це просто створює файл з назвою foobar. Звичайно NULL не надрукований, але я гарантую, що він пішов звідти через обмеження рядка C.
goldilocks

"текстові рядки закінчуються нульовим" -> Щоб пояснити далі: рядки завжди зберігаються з нульовим байтом в кінці, тому його "не дозволено" в тексті: Якщо ви вставили його, ви фактично припинили рядок в цей момент. Наприклад, foo[NULL]barзакінчиться як fooдля більшості намірів і цілей. Те, що не трапляється з цим, echo -eпоказує, що NULL десь було викреслено.
золотинок

5
Переважна більшість мов програмування дозволяють нульові символи в рядках. Просто буває, що основною мовою, що не є C, на якій побудовано Unix - і більшість оболонок Unix також не дозволяють нульові символи в рядках. У будь-якому випадку, @Tim, всі інтерфейси Unix використовують рядки з нульовим завершенням, тому нульовий байт - це одне, чого ви ніколи не можете мати в імені файлу (плюс /що є роздільником каталогів і не може бути цитується, тому може бути в імені шляху але не у назві файлу).
Жил "ТАК - перестань бути злим"

1
... але [не зауважуй знову]. Не те, що я б робив занадто часто, все одно. На мій погляд, немає ніяких причин, щоб вони були у текстових даних. Я б це виправив, але це коментар.
goldilocks

3

Причина багато в чому історична - НАЗАД назад у місцях проміжків часу не було дозволено у назвах файлів, тому пробіли використовувались як роздільники ключових слів / імен файлів. Майбутні перекладачі оболонок повинні бути зворотно сумісними зі старими сценаріями, і тому ми застрягли з головним болем у нас сьогодні.

Розробники процесів, яким не потрібно дуже сильно мати справу з людьми, можуть зробити це значно, набагато простіше, взагалі скинувши пробіли. Apple робить це, вміст / System / Library / CoreServices / містить дуже мало пробілів, програми з пробілами відкриваються від імені користувача, а WouldLookStrangeIfCamelCased. Подібні лише маршрути для Unix також уникають пробілів.

(дещо пов’язаний анекдот: у середині 90-х безпілотник Windows сказав "Назвіть одне, що можна зробити на Mac, що я не можу зробити в Windows" -> "Використовуйте 12 символів у імені файлу". -> Тиша. також можливо в цих 12 символів)


1
Раніше я використовував V6 Unix (c. 1978). Простіри тоді були дозволені. Одне із мене було: написати програму для розбору файлової системи (за допомогою прямого вводу-виводу диска) та пошуку файлу, який має назву пробілів та зворотних просторів.
wallyk

вони взагалі опускають пробіли - чи файли містять дуже мало пробілів?
mikeserv

2

Так що так, як уже багато разів зазначено в іншому місці, ім'я файлу може містити майже будь-який символ. Але потрібно сказати, що ім’я файлу - це не файл. Він має деяку вагу як атрибут файлу в тому, що вам зазвичай потрібне ім'я файлу, щоб відкрити файл, але ім'я файлу вказує лише на фактичний файл. Це посилання, що зберігається в каталозі, який його записав, поряд із номером inode - це набагато ближче наближення до фактичного файлу .

Отже, знаєте, називайте це все, що завгодно. Ядро байдуже - всі посилання на файли, з якими він буде оброблятися, все одно матимуть справу з реальними номерами inode. Файл річ для людського споживання - якщо ви хочете зробити його з розуму річ, ну, це ваша файлова система. Тут я зроблю кілька божевільних речей:

Спершу я створять 20 файлів і назву їх не що інше, як пробіли, кожне ім'я файлу містить ще один пробіл, ніж останній:

until [ $((i=$i+1)) -gt 20 ]
do  v=$v' ' && touch ./"$v"
done

Це якось смішно. Подивіться на моє ls:

ls -d ./*
./      ./          ./              ./                  ./                 
./      ./          ./              ./                  ./                  
./      ./          ./              ./                  ./                   
./      ./          ./              ./                  ./     

Зараз я збираюся відобразити цей каталог:

set -- * ; mkdir ../mirror
ls -i1qdU -- "$@" |
sh -c 'while read inum na
    do  ln -T "$1" ../mirror/$inum
    shift ; done' -- "$@"
ls -d ../mirror/*

Ось ../mirror/зміст:

../mirror/423759  ../mirror/423764  ../mirror/423769  ../mirror/423774
../mirror/423760  ../mirror/423765  ../mirror/423770  ../mirror/423775
../mirror/423761  ../mirror/423766  ../mirror/423771  ../mirror/423776
../mirror/423762  ../mirror/423767  ../mirror/423772  ../mirror/423777
../mirror/423763  ../mirror/423768  ../mirror/423773  ../mirror/423778

Гаразд, але, можливо, ви запитуєте - але що це добре? Як ви можете сказати, що це таке? Як ви можете бути впевнені, що ви пов’язали правильний номер вводу з правильним іменем файлу?

Добре...

echo "heyhey" >>./'    ' 
tgt=$(ls -id ./'    ')
cat ../mirror/${tgt%% .*} \
    $(ls -1td ../mirror/* | head -n1) 

ВИХІД

heyhey
heyhey

Дивіться, як номер inode, що міститься, так ../mirror/"${tgt%% .*}"і той посилання, ./' 'посилаючись на той самий файл. Вони описують той самий файл. Вони її називають, але більше нічого. Ніякої таємниці, насправді є лише якісь незручності, які ви могли б зробити собі, але в кінцевому підсумку це мало мати ніякого впливу на роботу вашої файлової системи Unix врешті-решт.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.