Рекурсивно искать каталог для каждого файла в каталоге на IBMi IFS

Я пытаюсь написать два (edit: shell) скрипта, и у меня возникли некоторые трудности. Я объясню цель, а затем предоставлю сценарий и текущий вывод.

1: получить список всех имен файлов в каталоге рекурсивно. Затем найдите содержимое всех файлов в этом каталоге для каждого имени файла. Должен возвращать путь, имя файла и номер строки каждого вхождения конкретного имени файла.

2: получить список каждого имени файла в каталоге рекурсивно. Затем найдите содержимое всех файлов в каталоге для каждого имени файла. Должен возвращать путь и имя файла каждого файла, который НЕ найден ни в одном из файлов в каталогах.

В конечном итоге я хочу использовать сценарий 2, чтобы найти и удалить (фактически переместить их в другой каталог для архивирования) неиспользуемые файлы на веб-сайте. Затем я хотел бы использовать сценарий 1, чтобы увидеть каждое вхождение и отфильтровать любые повторяющиеся имена файлов.

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

В настоящее время я тестирую это в системе IMBi в strqsh.

Моя структура тестовой папки:

scriptTest
---subDir1
------file4.txt
------file5.txt
------file6.txt
---subDir2
------file1.txt
------file7.txt
------file8.txt
------file9.txt
---file1.txt
---file2.txt
---file3.txt

У меня есть текст в некоторых из этих файлов, который содержит существующие имена файлов.

Это мой текущий сценарий 1:

#!/bin/bash
files=`find /www/Test/htdocs/DLTest/scriptTest/ ! -type d -exec basename {} \;`
for i in $files
do
    grep -rin $i "/www/Test/htdocs/DLTest/scriptTest" >> testReport.txt;
done

Прямо сейчас он работает правильно, за исключением предоставления пути к файлу, у которого есть совпадение. По умолчанию grep не возвращает путь к файлу?

Я немного дальше со сценарием 2:

#!/bin/bash
files=`find /www/Test/htdocs/DLTest/scriptTest/ ! -type d`
for i in $files
do
    #split $i on '/' and store into an array
    IFS='/' read -a array <<< "$i"

    #get last element of the array 
    echo "${array[-1]}"

    #perform a grep similar to script 2 and store it into a variable
    filename="grep -rin $i "/www/Test/htdocs/DLTest/scriptTest" >> testReport.txt;"

    #Check if the variable has anything in it
    if [ $filename = "" ]   
            #if not then output $i for the full path of the current needle.
        then echo $i;
    fi
done

Я не знаю, как разбить строку $i в массив. Я получаю сообщение об ошибке в строке 6

001-0059 Syntax error on line 6: token redirection not expected.

Я планирую попробовать это на реальном дистрибутиве Linux, чтобы увидеть, получаю ли я другие результаты.

Я ценю любое понимание в продвинутом.

1 ответ

Вступление

Это не совсем полное решение, так как я не уверен на 100%, что понимаю, что вы пытаетесь сделать. Тем не менее, ниже приведены фрагменты решения, которые вы можете объединить, чтобы сделать то, что вы хотите.

Создать тестовый жгут

cd /tmp
mkdir -p scriptTest/subDir{1,2}
mkdir -p scriptTest/subDir1/file{4,5,6}.txt
mkdir -p scriptTest/subDir2/file{1,8,8}.txt
touch scriptTest/file{1,2,3}.txt

Поиск и удаление дубликатов

В самом общем смысле, вы можете использовать поиск -exec флаг или цикл Bash для запуска grep или другого сравнения ваших файлов. Однако, если все, что вы пытаетесь сделать, это удалить дубликаты, то вам может быть лучше использовать утилиты fdupes или duff для идентификации (и, при необходимости, удаления) файлов с дублированным содержимым.

Например, учитывая, что все файлы.txt в тестовом корпусе являются дубликатами нулевой длины, рассмотрим следующие примеры duff и fdupes.

фальсифицировать

Дафф имеет больше опций, но не удаляет файлы напрямую. Скорее всего, вам понадобится команда duff -e0 * | xargs -0 rm удалить дубликаты. Чтобы найти дубликаты, используя сравнения по умолчанию:

$ duff -r scriptTest/
8 files in cluster 1 (0 bytes, digest da39a3ee5e6b4b0d3255bfef95601890afd80709)
scriptTest/file1.txt
scriptTest/file2.txt
scriptTest/file3.txt
scriptTest/subDir1/file4.txt
scriptTest/subDir1/file5.txt
scriptTest/subDir1/file6.txt
scriptTest/subDir2/file1.txt
scriptTest/subDir2/file8.txt

fdupes

Эта утилита предлагает возможность удалять дубликаты напрямую различными способами. Одним из таких способов является призыв fdupes . --delete --noprompt как только вы уверены, что готовы продолжить. Однако, чтобы найти список дубликатов:

$ fdupes -R scriptTest/
scriptTest/subDir1/file4.txt            
scriptTest/subDir1/file5.txt
scriptTest/subDir1/file6.txt
scriptTest/subDir2/file1.txt
scriptTest/subDir2/file8.txt
scriptTest/file1.txt
scriptTest/file2.txt
scriptTest/file3.txt

Получить список всех файлов, включая недубликаты

$ find scriptTest -name \*.txt
scriptTest/file1.txt
scriptTest/file2.txt
scriptTest/file3.txt
scriptTest/subDir1/file4.txt
scriptTest/subDir1/file5.txt
scriptTest/subDir1/file6.txt
scriptTest/subDir2/file1.txt
scriptTest/subDir2/file8.txt

Затем вы можете действовать на каждый файл с находкой -exec {} + или просто использовать grep, который поддерживает --recursive --files-with-matches флаги для поиска файлов с соответствующим содержимым.

Передача результатов поиска в цикл Bash в виде массива

В качестве альтернативы, если вы точно знаете, что в именах файлов не будет пробелов, вы также можете использовать массив Bash для хранения файлов в переменной, которую вы можете перебирать в цикле Bash for. Например:

files=$(find scriptTest -name \*.txt)
for file in "${files[@]}"; do
  : # do something with each "$file"
done

Подобные циклы часто медленнее, но могут предоставить вам дополнительную гибкость, необходимую вам, если вы делаете что-то сложное. YMMV.

Другие вопросы по тегам