2009-07-23 3 views
0

У меня есть папка, в которой есть много папок внутри, каждая из которых содержит файл фильма. Теперь я хочу видеть все эти фильмы за один раз (но мне нужно сохранить структуру папок), поэтому я хотел символизировать их все в папку верхнего уровня (плоский вид в Directory Opus был бы здесь, но я 'm на mac). Вот моя попыткасценарий оболочки для связывания определенных файлов на одном уровне

for file in */*/*.mov; 
do 
newname='echo $file | sed "s|[^/]*/[^/]*/||g"'; 
ln -s $file echo $newname; 
done 

Так что я пытаюсь сделать на линии 3 повернуть путь Foo/бар/spud.mov в spud.mov, а затем на линии 4 сделать пер -s Foo/бар/Спада .mov spud.mov

Но это не работает, все это я получаю

пер: "s | [^ /] /[^ /]/|| г": нет такого файл или справочник

I ' вы пробовали различные комбинации кавычек и побегов, но не повезло. Эффект sed работает, но я, очевидно, что-то сделал с моими переменными.

Благодаря

ответ

2

Что со всем echo $ file | sed или awk, в любом случае? basename сделано для этой цели.

for file in */*/*.mov; do 
    newname=`basename $file1 
    ln -s $file $newname; 
done 

Но, на самом деле, пер делает то же самое, когда данный каталог, так:

for file in */*/*.mov; do 
    ln -s "$file" . 
done 

Или вариант действительно общего назначения, который достаточно умен, чтобы только вызов ¯Ln столько раз, сколько необходимо:

find . -name \*.mov -depth +1 -print0 | xargs -0 -J % ln -s % . 

То есть, в локальном каталоге, найти все с именем, заканчивающимся на .mov, что это не в текущей директории (глубина более 1), отделить вывод нулями, и трубы в xargs, который L ooking для NULL-отдельного входа и будет проходить. как аргумент для ln после всех аргументов, которые он читал на stdin.

1

Basename является то, что вы хотите, и проблема с вашим решением является бедной процитировать:

 
bash-3.2$ echo $file 
foo/bar/spud.mov 
bash-3.2$ newname=$(echo $file | sed 's|[^/]*/[^/]*/||g'); echo $newname 
spud.mov 
2

Это будет делать то же самое для всех уровней папок:


for i in `find . -name "*.mov"` 
do 
    file=`echo $i | /bin/awk -F'/' '{print $NF}'` 
    /bin/ln -s $i $file 
done 
+0

Обычный способ получить последний компонент пути - это команда basename: 'ln -s $ i $ (basename $ i)' –

+0

его нормально использовать базовое имя для одного из двух файлов, однако для многих файлов, использование возможностей внутренней оболочки оболочки для получения «basename» намного более эффективно. – ghostdog74

+0

вам не нужно ни того, ни другого; просто "." работает, потому что при передаче каталога в качестве последнего аргумента ln -s делает то же самое ... – freiheit

0

Хорошо, спасибо всем. Кажется, это несколько червей в этой банке. Похоже, что то, что я делал, хотя и не лучшим образом, сработало бы, если бы я использовал правильный синтаксис.

Но я узнал о basename и улучшил свои знания об этом, поэтому я счастлив.

0

Я знаю немного больше о том, как использовать найти, так что теперь я могу сделать это в одной строке:

find . -name "*.mov" -exec ln -s {} \; 

-exec флаг в команде находят позволяет запустить другой процесс каждый раз, когда это находит файл. Поместите пару фигурных скобок, как указано выше, чтобы этот процесс обрабатывал файл как параметр. Потребовал мне время, чтобы понять, что перед побежденной точкой с запятой должно быть пространство.

Смежные вопросы