3

По какой-то причине этот скрипт выводит три файла для каждого оригинала, а не один.

Должно быть, я допустил небольшую ошибку - я новичок в этом!

Очень признателен, если кто-нибудь сможет объяснить, почему это происходит.

Сценарий:-

for f in *.txt
do
   noOfRows=$(cat $f | wc -l)
   relevantRows=$(expr $noOfRows - 5)
   head -n $relevantRows $f | tee ${f%.txt}-Amended.txt
done

Результат команды ls:-

E12-5_F2_NEG-Amended-Amended-Amended.txt  E12-5_M3_POS-Amended-Amended-Amended.txt
E12-5_F2_NEG-Amended-Amended.txt          E12-5_M3_POS-Amended-Amended.txt
E12-5_F2_NEG-Amended.txt                  E12-5_M3_POS-Amended.txt
E12-5_F2_NEG.txt                          E12-5_M3_POS.txt
E12-5_F2_POS-Amended-Amended-Amended.txt  E12-5_M4_NEG-Amended-Amended-Amended.txt
E12-5_F2_POS-Amended-Amended.txt          E12-5_M4_NEG-Amended-Amended.txt
E12-5_F2_POS-Amended.txt                  E12-5_M4_NEG-Amended.txt
E12-5_F2_POS.txt                          E12-5_M4_NEG.txt
E12-5_F5_NEG-Amended-Amended-Amended.txt  E12-5_M4_POS-Amended-Amended-Amended.txt
E12-5_F5_NEG-Amended-Amended.txt          E12-5_M4_POS-Amended-Amended.txt
E12-5_F5_NEG-Amended.txt                  E12-5_M4_POS-Amended.txt
E12-5_F5_NEG.txt                          E12-5_M4_POS.txt
E12-5_F5_POS-Amended-Amended-Amended.txt  E12-5_M7_NEG-Amended-Amended-Amended.txt
E12-5_F5_POS-Amended-Amended.txt          E12-5_M7_NEG-Amended-Amended.txt
E12-5_F5_POS-Amended.txt                  E12-5_M7_NEG-Amended.txt
E12-5_F5_POS.txt                          E12-5_M7_NEG.txt
E12-5_M3_NEG-Amended-Amended-Amended.txt  E12-5_M7_POS-Amended-Amended-Amended.txt
E12-5_M3_NEG-Amended-Amended.txt          E12-5_M7_POS-Amended-Amended.txt
E12-5_M3_NEG-Amended.txt                  E12-5_M7_POS-Amended.txt
E12-5_M3_NEG.txt                          E12-5_M7_POS.txt

Большое спасибо, Адам

2 ответа2

5

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

Поскольку E12-5_F2_NEG-Amended.txt оканчивается на .txt он будет выбран вашим скриптом при следующем запуске.

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

Если скрипт выведет в $f.new а не в ${f%.txt}-Amended.txt , у вас не возникнет этой проблемы.

В качестве альтернативы поместите rm *Amended.txt в начале программы. Если у вас очень большое количество файлов в каталоге, это может замедлить работу в старых версиях Unix.

Другой вариант - вывести файлы в подкаталог (например, "new/${f%.txt}.Amended.txt")

3

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

head --lines=-5 input.txt > output.txt

В цикле:

for f in *.txt; do head --lines=-5 "$f" > "${f%.txt}-Amended.txt"; done

Вы можете использовать -n -5 вместо --lines=-5 чтобы сэкономить при наборе текста, если хотите.

Как указывает RedGrittyBrick, причина в том, что у вас есть три файла на вход, вероятно, потому, что вы запускали сценарий несколько раз, и поскольку выходные данные заканчиваются на .txt, они были подобраны глобусом * .txt последовательных сценариев.

Сейчас я буду критиковать ваш конкретный сценарий.

noOfRows=$(cat $f | wc -l)

Это действительно бесполезное использование кошки ; а не cat $f | wc -l , используйте wc -l "$f" . Это, вероятно, не так важно в этом конкретном сценарии, но хорошо не развивать вредные привычки. Говоря о вредных привычках: всегда заключайте в кавычки переменные , например, "$f" . Это позволит убедиться, что имя файла обрабатывается как один аргумент, даже если оно содержит пробелы.

relevantRows=$(expr $noOfRows - 5)

Здесь нет ничего плохого, хотя я бы предпочел использовать что-то вроде

relevantRows=$((noOfRows-5))

AFAIK нет никакой разницы в производительности между этими двумя, но я нахожу способ bash более визуально приятным; и что еще более важно, способ, который я описал, определен в POSIX и, таким образом, является более переносимым. Только в bash (так что не используйте это, если вам нужно перенести скрипт в другую оболочку), лучший способ сделать это в скрипте - использовать let:

let noOfRows-=5

... что вычтет 5 из числа, содержащегося в переменной $ noOfRows, что означает, что нет необходимости создавать переменную $ relatedRows.

head -n $relevantRows $f | tee ${f%.txt}-Amended.txt

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .