2013-11-17 2 views
6

Просто новый скрипт Bash и программирование в целом. Я хотел бы автоматизировать удаление первой строки из нескольких файлов .data в каталоге. Мой сценарий выглядит следующим образом:Петля для удаления первой строки из нескольких файлов с использованием Bash Script

#!/bin/bash 
for f in *.data ; 
do tail -n +2 $f | echo "processing $f"; 
done 

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

Заранее благодарен

ответ

3

Вы не меняете сам файл. Используя tail, вы просто читаете файл и печатаете его части на stdout (терминал), вы должны перенаправить этот вывод во временный файл и затем перезаписать исходный файл временным.

#!/usr/bin/env bash 
for f in *.data; do 
    tail -n +2 "$f" > "${f}".tmp && mv "${f}".tmp "$f" 
    echo "Processing $f" 
done 

Более того, не ясно, что вы хотите достичь с помощью команды echo. Почему вы используете трубу (|)?

даст вам более простой способ достичь этого. См. Ответ devnull.

+0

Спасибо, это сработало и с очень полезным объяснением. Обоснование моего кода заключалось в том, что я хотел удалить строку с помощью 'tail', а затем получить уведомление о том, что это сделало это, повторив его на терминал ..., чтобы увидеть, где я был, с точки зрения его завершения 1000+ файлов , Спасибо за ваши комментарии об использовании 'tail', я обязательно буду использовать его правильно в будущем. – Marko

11

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

Потому что просто tail ing не изменит файл.

Вы можете использовать sed, чтобы изменить файлы на месте с отключенной первой линией. Говоря

sed -i '1d' *.data 

будет удалить первую строку из всех .data файлов.


EDIT: BSD sed (на OSX) будет ожидать аргумент -i, так что вы можете либо указать расширение для резервного копирования старых файлов, или редактировать файлы на месте, говорят:

sed -i '' '1d' *.data 
+0

Приветствие Я попробовал это (в тестовом каталоге с скопированными файлами), и я получил следующий вывод: ** СЭД: 1: «201001010000a.WAH.data»: командовать ожидает \ с последующим текстом ** – Marko

+0

@ Marko Кажется, что вы не выполнили правильную команду. Поскольку вы уже скопировали файлы в новый каталог, вы можете просто скопировать/вставить команду, упомянутую выше. – devnull

+0

По-прежнему не повезло, может быть, проблема с 'sed' на OSX? – Marko

0

я бы сделал это так:

#!/usr/bin/env bash 
set -eu 
for f in *.data; do 
    echo "processing $f" 
    tail -n +2 "$f" | sponge "$f" 
done 

Если вы не имеете sponge вы можете получить его в moreutils пакете.

Важные цитаты вокруг имени файла - они заставят его работать с именами файлов, содержащими пробелы. И вещь env в верхней части так, чтобы люди могли установить, какой интерпретатор Bash они хотят использовать через их PATH, в случае, если у кого-то есть нестандартный. set -eu делает выход Bash, если возникает ошибка, что обычно более безопасно.

+0

Отличная информация, приветствия! – Marko

0

ed стандартный редактор:

shopt -s nullglob 
for f in *.data; do 
    echo "Processing file \`$f'" 
    ed -s -- "$f" < <(printf '%s\n' "1d" "wq") 
done 

shopt -s nullglob здесь только потому, что вы всегда должны использовать это при использовании шариков, особенно в сценарии: он будет делать шарики расширяться ничего, если нет совпадений; вы не хотите запускать команды с неконтролируемыми аргументами.

Далее мы выполняем цикл по всем файлам и использовать ed с командами:

  • 1: перейти на первую линию
  • d: удалите эту строку
  • wq: написать и бросить

Опции для ed:

  • -s: сообщает ed, чтобы заткнуться! мы не хотим, чтобы ed печатал свой мусор на нашем экране.
  • --: конец вариантов: это сделает ваш скрипт более надежным, если имя файла начинается с hypen: в этом случае дефис путает ed, пытаясь обработать его как опцию. С --, ed знает, что после этого больше нет параметров, и он будет успешно обрабатывать любые файлы, даже те, которые начинаются с дефиса.
Смежные вопросы