Как я могу перечислить файлы, в которых нет символических ссылок?

10

У меня большой каталог myfiles, полный разных документов, и я не хочу изменять его структуру.

Поэтому я создал (несколько) других каталогов для каждого класса документов. Например, у меня есть каталог «images», в котором есть символические ссылки на каждый файл .jpgили .cr2файл в каталоге «myfiles» плюс другие описательные файлы для каждой символической ссылки (с тем же именем файла) с описанием и другими метаданными. Символические ссылки в каталоге / images могут иметь имя, отличное от исходного связанного файла.

Я пытаюсь найти самый простой способ убедиться, что каждый файл изображения в каталоге «myfiles» имеет символическую ссылку на каталог «images».

Смотрите пример структуры папок

/myfiles/a.doc
/myfiles/b.jpg
/myfiles/c.cr2
/myfiles/d.mov

должен привести

/images/b_800x600.jpg
/images/b_800x600.desc
/images/c_3820x5640.cr2
/images/c_3820x5640.cr2
Роберт Александр
источник
Не полный ответ, но вы можете сохранить результаты a find /myfiles -type fв файл, а затем использовать, find /images -type l -exec readlink {} \; | egrep myfilesчтобы получить список файлов, в которых есть символические ссылки, а /imagesзатем перебрать результаты, выполнив a sedдля каждого из них, чтобы удалить пути в первом сохраненном файле, поскольку они уже иметь символьную ссылку, а оставшиеся файлы - это файлы, которые не имеют символической ссылки.
Братчли
2
Можно ли вместо этого использовать жесткие ссылки, чтобы вы могли использовать счетчик жестких ссылок, чтобы увидеть, есть ли у вас ссылки? Используя ls -lвы можете увидеть количество жестких ссылок во втором столбце.
Ламберт
Делай то, что говорит @ Ламберт. rmэти каталоги ссылок и используют, pax -rwl -s "\|.*regex|modifes_filename|" /path/to/myfiles/*.jpg /path/to/jpg_dirнапример, для получения жестких ссылок с программно измененными именами файлов только для тех файлов, которые соответствуют вашим jpgs. Вы можете получить намного больше от этого - например, пакетирование, основанное на времени изменения и т. Д.
mikeserv

Ответы:

6

Если я правильно понял вопрос, вам нужны файлы в myfiles, которые не имеют символических ссылок в изображениях:

#!/bin/bash

OIFS="$IFS"
IFS=$'\n'

files="$(find myfiles/ -type f -name '*.jpg' -or -name '*.cr2')"
for f in $files; do
    list="$(find -L images/ -xtype l -samefile "$f")"
    if [[ "$list" == "" ]]; then
        echo "$f does not have symlink."
    fi
done

IFS="$OIFS"

При таком подходе есть предостережение, если у вас есть файл a.jpg в каталоге myfiles / 1, и у вас есть символическая ссылка на этот файл в каталоге images / 3 или просто в images / файл не будет сообщаться с отсутствующей символической ссылкой.

taliezin
источник
Спасибо ! Да, вы правильно поняли. Близко, но не совсем. Моя вина не твоя :-) Пример, который я привел, показывает упрощенный каталог myfiles. В действительности файлы изображений под myfiles могут находиться внутри любого произвольного уровня вложенных каталогов.
Роберт Александр
Я отредактировал ответ для поиска во всех моих файлах, но проверьте, если это то, что вы хотите.
taliezin
ПОЧТИ там :-) Ваш скрипт икает, когда в файлах есть пробелы (и, возможно, другая хрень, такая как одиночные апострофы) ...
Robert Alexander
Я думаю, теперь это должно быть хорошо
taliezin
Ваша последняя модификация разбивает каждое f в каждой букве n! :-) Я связал строку IFS с IFS =, затем с новой строки с клавиатуры, затем с другой ". Теперь разделение работает, но я получаю длинную последовательность" missinglinks.sh: 11: missinglinks.sh: [[: not found "
Роберт Александр,
3

Я предполагаю, что файлы myfilesне являются символическими ссылками, и что ни одно из имен файлов не содержит символов новой строки. (Мой подход все еще может работать, если эти предположения нарушаются, но он становится более сложным.) Я также предполагаю, что у вас есть общая readlinkутилита и она поддерживает -fканонизацию путей, как в случае Linux (как GNU, так и BusyBox), но не на, например, OSX.

Создайте список файлов и рассортируйте его по порядку:

find /myfiles -type f -print | sort >all.list

Составьте список целей символических ссылок с абсолютными путями.

find /images -type f -exec readlink -f {} \; | sort >linked.list

Список файлов, которые не связаны:

comm -32 all.list linked.list

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

comm -23 <(find /myfiles -type f -print | sort) \
         <(find /images -type f -exec readlink -f {} \; | sort)

Если ссылки ниже /imagesабсолютные, вы можете использовать их readlinkбез -fопции, доступной в * BSD и OSX.

Жиль "ТАК - прекрати быть злым"
источник
Я собирался опубликовать что-то вроде вашей commкоманды, но я не буду сейчас, когда я вижу, что вы уже сделали. Однако перенаправление с sortне имеет смысла; тогда подстановки процесса ничего не выведут. Кроме того, вы можете добавить множество каталогов рядом с ними, /imagesесли вы хотите найти файлы, в /myfilesкоторых нет символической ссылки ни из одного из ряда каталогов, кроме /images.
tripleee
1
Видеть Stackoverflow.com/questions/7665/… для альтернативreadlink -f
tripleee
@tripleee Я забыл удалить перенаправление, когда создал версию перенаправления процесса, спасибо. Да, вы можете легко добавить другие каталоги или внести другие изменения.
Жиль "ТАК - перестать быть злым"