Блог Олега Сердюкова

Работа в shell с именами файлов с пробелами и другими сложными для обработки символами

Понадобилось мне восстановить из бекапа Time Machine небольшой скрипт. Ситуация осложнялась тем, что я его несколько раз менял, потом написал с нуля, потом стёр, в итоге в архиве Time Machine было множество вариантов. Нужный скрипт был с характерными первыми строками. В репозиторий git я скрипт не вносил, что не облегчало мою задачу.

Итак, к делу. Запуск терминала, подключение диска Time Machine, переход в нужный каталог:

$ cd /Volumes/Time\ Machine\ Backups/Backups.backupdb/ComputerName

Ищу варианты:

$ ls -al */*/Users/ctrld/bin/apps.sh
rwxr-xr-x@ 2 ctrld  staff   918 Mar  3  2011 2011-04-08-195358/Macintosh HD/Users/ctrld/bin/apps.sh
-rwxr-xr-x@ 2 ctrld  staff   971 Apr 30 17:52 2011-06-06-124551/Macintosh HD/Users/ctrld/bin/apps.sh
-rwxr-xr-x@ 2 ctrld  staff  1024 Jun 10 20:14 2011-06-14-111524/Macintosh HD/Users/ctrld/bin/apps.sh

Первая мысль - скормить файлы в команду head:

$ ls */*/Users/ctrld/bin/apps.sh | xargs head -5

Конечно же, эта конструкция неправильная, так как в именах есть пробелы:

head: 2011-02-19-180439/Macintosh: No such file or directory
head: HD/Users/ctrld/bin/apps.sh: No such file or directory

==> 2011-08-31-111236/Lion/Users/ctrld/bin/apps.sh <==
#!/bin/sh
APPDIR="/Volumes/Data/iTunes/iTunes Music/Mobile Applications/"
find "${APPDIR}" -name \*.ipa |
while read line
do

Как же заставить xargs считать путь с пробелом, как единый параметр? Эврика, вспоминаю о замечательной статье ”Fixing Unix/Linux/POSIX Filenames: Control Characters (such as Newline), Leading Dashes, and Other Problems”. На выходе получаю команду:

$ find */*/Users/ctrld/bin -name apps.sh -type f -print0 | xargs -0 head -3
==> 2011-02-19-180439/Macintosh HD/Users/ctrld/bin/apps.sh <==
#!/bin/sh
APPDIR="/Users/$USER/Music/iTunes/iTunes Music/Mobile Applications"
find "${APPDIR}" -name \*.ipa |

==> 2011-03-03-210012/Macintosh HD/Users/ctrld/bin/apps.sh <==
#!/bin/sh
#APPDIR="/Users/$USER/Music/iTunes/iTunes Music/Mobile Applications"
APPDIR=$(find `defaults read com.apple.iTunes NSNavLastCurrentDirectory:ChooseObject:0` -name "Mobile Applications")

Нужный вариант найден и восстановлен. Для чего этот скрипт? Для ”получения информации по приложениям iPhone в iTunes из shell”.

Всем, кто работает с shell категорически рекомендую изучить статью ”Fixing Unix/Linux/POSIX Filenames: Control Characters (such as Newline), Leading Dashes, and Other Problems” - она убережёт вас от ошибок при обработке параметров.

Comments