Невозможно переместить правильные файлы в mvfiles - PullRequest
0 голосов
/ 10 декабря 2018

Я пытаюсь использовать grep для разделителей (запятая, труба или точка с запятой) в нескольких файлах.

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

filename=$(find /opt/interfaces/sample_check -type f \( -name "*message.txt*" -or -name "*comma2*" -or -name "*comma3*" \))
pathname=/opt/interfaces/sample_check

echo $filename
echo $pathname

if `head -1 $filename | grep -o [';']`; then

    echo "Found"
else
    mv $filename /opt/interfaces/sample_check/mvfiles
fi

Ответы [ 4 ]

0 голосов
/ 10 декабря 2018

Попробуйте использовать grep -L для вывода списка файлов, которые не совпадают.

find $pathname -type f \( -name "*message.txt*" -or -name "*comma2*" -or -name "*comma3*" \) | xargs egrep -L ";|,|\|" | xargs  -IX mv  X $pathname/mvfiles

В приведенном выше примере я использую egrep из-за условий OR для pipe.То есть мы хотим указать несколько регулярных выражений для соответствия.Если файл содержит любой из;, |имя файла не будет выводиться egrep.Это оставляет только файлы, которые не соответствуют, передаются в xargs.В версии xargs для Mac вы можете указать строку замены с параметром -I.Для каждого имени файла, выводимого egreg, xargs будет вызывать mv $ pathname / mvfiles.

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

awk ' FNR == 2 && /[;|,]/ { print FILENAME } ' * 

Приведенный выше awk будет отображать текущее имя файла (FILENAME), когда номер записи файла (FNR) равен 2 (вторая строка в каждом файле) ивходная строка соответствует регулярному выражению [; |,].

Чтобы вставить этот бит кода в мой ответ выше, вы можете сделать это:

find $pathname -type f \( -name "*message.txt*" -or -name "*comma2*" -or -name "*comma3*" \) | xargs awk ' FNR == 2 && /[;|,]/ { print FILENAME } '   | xargs  -IX mv  X $pathname/mvfiles

Итак, выше, я заменил 'xargs egrep' на 'xargs awk'.Кроме того, я удалил * из конца команды awk, потому что это, по сути, функция xargs по умолчанию - взять все входные данные в stdin и предоставить их в качестве входных данных для команды (в данном случае awk).

Так какмы используем awk, мы можем фактически избежать последнего использования xargs для перемещения файлов.Вместо этого мы можем построить команды и направить их в bash (или какую-либо оболочку).

Вот версия, в которой мы передаем команды в bash:

find $pathname -type f \( -name "*message.txt*" -or -name "*comma2*" -or -name "*comma3*" \) | xargs awk ' FNR == 2 && /[;|,]/ { print "mv " FILENAME  " '$pathname'/mvfiles" } '   | bash

Если вы хотите просто отладитьВышеупомянутое утверждение без каких-либо действий, вы можете удалить команду bash в конце, чтобы оставить эту отладочную версию:

Отладочная версия (не перемещает файлы - только печатает команды mv):

find $pathname -type f \( -name "*message.txt*" -or -name "*comma2*" -or -name "*comma3*" \) | xargs awk ' FNR == 2 && /[;|,]/ { print "mv " FILENAME  " '$pathname'/mvfiles" } '  
0 голосов
/ 10 декабря 2018

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

pathname=/opt/interfaces/sample_check
find "$pathname" -type f \( -name "*message.txt*" -or -name "*comma[23]*" \) |
  while read -r filename
  do if sed -n '1d; 2{ /[,;|]/q0 }; q1' "$filename"
     then echo "Delimited: $filename"
     else echo "Moving ==>> $filename"
          mv "$filename" /opt/interfaces/sample_check/mvfiles/
     fi
  done

Поскольку мы хотим выбирать только на основе разделителей в строке 2 файла, давайте используем sed вместо.

sed -n '1d; 2{/[,;|]/q0 }; q1' 

sed -n говорит, что ничего не печатать, если не требуется - нам не нужен вывод.

1d удаляет первую строку (мы не редактируем, просто отказываемся от дальнейшегообработка в этой строке, поэтому она пропускает остальную часть программы.)

2{...} говорит, что эти команды нужно выполнять только в строке 2. /[,;|]/q0 говорит, что в строке есть запятая, точка с запятой или труба, затем закройтес кодом завершения zeo, указывающим на успех.

q1 говорит, что если он попадет сюда, завершается с кодом выхода 1.

Они запускают ветвление if.:)

0 голосов
/ 10 декабря 2018

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

# pathname is your directory you want files to search in
pathname=/opt/interfaces/sample_check

# here you can add different filenames that you want to match. I.e. only take files in the loop which contain filename1 in the name, or starts with filename2, or starts with filename3.
find $pathname -type f \( -name "*filename1*" -or -name "filename2*" -or -name "filename3*" \) -print0 |
while IFS= read -r -d '' file; do
    if grep -e '[|;,]' "$file"
      then
        echo "Found in $file."
    else
        echo "Not found in $file. Moving to directory xxx."
        mv "$file" /opt/interfaces/sample_check/mvfiles
    fi
done
0 голосов
/ 10 декабря 2018

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

pathname=/opt/interfaces/sample_check
echo $pathname

find "$pathname" -type f \( -name "*message.txt*" -or -name "*comma2*" -or -name "*comma3*" \) | while read filename
do

    echo $filename

    if head -1 "$filename" | grep '[;]' >/dev/null; then

        echo "Found"
    else
        mv "$filename" "$pathname/mvfiles/."
    fi
done

Конечно, есть и другие варианты решения проблемы.

Вы также можете использовать grep -q '[;]' вместо grep '[;]' >/dev/null на современномВ системах, но в старых системах опция -q может не работать.

Примечание. Я использовал .../mvfiles/., предполагая, что mvfiles - это существующий каталог.Это позволяет избежать перезаписи или создания файла с тем же именем в случае, если каталог не существует.Кроме того, я использовал кавычки, чтобы избежать проблем с именами файлов, содержащими пробелы.

...