поиск каталогов, содержащих один файл и отсутствующих в другом

Вы указываете только один "URL", следующая программа Python поддерживает их список:

urls = [
    '/test/test',
    ]

years = [1999, 2000, 2001]

for url in urls:
    for year in years:
        spliturl = url.split('/')
        spliturl.insert(2, str(year))
        print('/'.join(spliturl))

Хитрость заключается в том, чтобы вставить год во второй позиции, первая позиция spliturl - это пустая строка (то есть строка перед первыми /).

3
24.07.2017, 12:51
3 ответа

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

for dir in */; do [ ! -e "$dir"/"$filename" ] || printf '%s\n' "$dir"; done

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

for dir in */; do 
    [ ! -e "$dir"/"$filename1" ] && 
    [ -e "$dir"/"$filename2" ] && 
    printf '%s\n' "$dir"; 
done

Или, в несколько более ясном синтаксисе:

for dir in */; do 
    if [ ! -e "$dir"/"$filename1" ]; then 
        if [ -e "$dir"/"$filename2" ]; then 
            printf '%s\n' "$dir"; 
        fi 
    fi
 done

Все это делается с помощью встроенных -инструментов оболочки. В частности:

  • [:this и сопутствующий ]являются синонимами для testвстроенного (см. help [или help testпри использовании оболочки в стиле sh -). Это способы написания тестовых операций в оболочке.
  • -e:это проверяет, существует ли файл/каталог и т.д. См. help test. Простой формат — :[ -e file ], который вернет true, если fileсуществует.
  • [ ! -e filename ]:!просто инвертирует тест. Таким образом, [ ! -e file ]будет истинным, если fileне существует не .

В совокупности это означает, что приведенная выше команда выполняет:

## Iterate over every directory (dirs only because of the '/' in '*/')
## saving each of them in the variable $dir.
for dir in */; do 
    ## If this $dir does not contain $filename1
    if [ ! -e "$dir"/"$filename1" ]; then 
        ## If this $dir does contain $filename2
        if [ -e "$dir"/"$filename2" ]; then 
            ## Print the directory name
            printf '%s\n' "$dir"; 
        fi 
    fi
done

Чтобы запустить это, конечно, вам нужно сначала установить $filename1и $filename2соответственно. Например:

filename1="unwantedFile"
filename2="wantedFile"
3
27.01.2020, 21:09

Вы также можете определить нужные каталоги следующим образом:

find. -maxdepth 2 -path '*/*/wanted.txt' -type f \
  -execdir test ! -f unwanted.txt \; -execdir pwd \;

Это работает следующим образом:

  • Ищем записи до глубины 2.
  • Параметр -pathдополнительно ограничивает их глубину ровно 2 из-за наличия 2 косых черт, так как максимальная глубина не позволяет идти дальше, а 2 явных косых черты не позволяют углубиться ниже 2.
  • Запись Wanted.txt, найденная на уровне глубины 2, должна быть обычным файлом, обеспеченным-type f
  • Параметр -execdirповысит уровень операции до каталога, в котором находится требуемый.txt, и, следовательно, команда testбудет искать там нежелательный файл.
  • Затем нужно просто распечатать каталог (, повышенный из-за -execdir), где нежелательный файл не был найден.
  • Не останавливаясь на этом, скажем, что каталог может содержать конкретный файл только один раз, следовательно, операции -execdirвыполняются один раз / каталог и только в тех каталогах, которые наверняка содержат обычные файлы Want.txt.
4
27.01.2020, 21:09

С помощью zsh, чтобы вывести список каталогов в текущем каталоге, которые содержат файл musthave, а не файл mustnothave:

contain() [[ -e $REPLY/$1 || -L $REPLY/$1 ]]

printf '%s\n' *(D/e(contain musthave)^e(contain mustnothave))

Обратите внимание, что выполнение:

find... -exec sh -c 'ls {}' \;

не только не переносим, ​​но и является уязвимостью для внедрения команд. Например, если есть каталог с именем $(reboot)или ;reboot, в нем будут запущены командные строки ls $(reboot)или ls ;reboot, вызывающие перезагрузку. {}никогда не следует встраивать в аргумент кода (языка shили любого другого языка ), где он может быть неверно истолкован. Используйте:

find... -exec sh -c 'ls "$1"' sh {} \;

вместо этого.

3
27.01.2020, 21:09

Теги

Похожие вопросы