Распечатайте первую и последнюю строку всех файлов в папке

В зависимости от Вашего дистрибутива Linux и вида установки (минимальный, настольно-центральный, и т.д.) atatd в демоне планировщика заданий), установлен по умолчанию или нет.

Для проверки его, можно дать команды как:

$ which at
/usr/bin/at
$ which atd
/usr/bin/atd
$ yum whatprovides atd # to get the package name 
$ yum info pkg-name # to see if it is installed

(принятие конфетки доступно на SuSe - использование системы Fedora здесь),

Если пакет не установлен, можно установить его через диспетчер пакетов, например, что-то как:

$ yum install at # on fedora at least

Если это установлено, возможно, демон не запускается на начальной загрузке по умолчанию.

Видеть если это выполнение:

$ pgrep -l atd

Или просто протестируйте его как это

$ echo echo hello world | at now

(смотрите, Ваша система входит в систему другой терминал, и/или проверьте свой локальный почтовый ящик),

Как запустить, это зависит от Вашей init-системы, если бы это является олдскульным, это было бы что-то как:

$ /etc/init.d/atd start

Если бы это - systemd, это было бы что-то как:

$ systemctl start atd

Поскольку init.d основывал систему также для systemd каждый, там также команды, чтобы отобразить состояние сервиса как фактическое время отправления и заставить его запуститься на начальной загрузке.

Но скорее всего atd запускается по умолчанию после того, как установка и это являются установкой по умолчанию, чтобы быть запущенными при начальной загрузке системы.

3
23.12.2014, 19:59
8 ответов

Так что мне нравится SED Ответ может быть

for file in file.log.*
do
   echo "file: $file"
   echo -n "first line: "
   cat "$file" | sed -n '/^\s*$/!{p;q}'
   echo -n "last line: "
   tac "$file" | sed -n '/^\s*$/!{p;q}'
done
6
27.01.2020, 21:08

Попробуйте:

awk -F'\n' -vRS="" '
  {
    print "file: " FILENAME;
    gsub(/\n[[:blank:]]+|[[:blank:]]+\n/,"");
    print "first line: " $1;
    print "last line: " $NF;
  }
' file.log.*
2
27.01.2020, 21:08

Другим подходом было бы использование головы и хвоста :

EDIT (Спасибо за предложение @don_crissti! )

for file in file.log.*
do
   echo "file: $file"
   echo -n "first line: "
   grep -v '^\s*$' "$file" | head -n1
   echo -n "last line: "
   grep -v '^\s*$' "$file" | tail -n1
done
2
27.01.2020, 21:08

Для полноты, вот SD-ответ, который один раз читает через каждый файл (надеюсь, быстрее, чем несколько SED , CAT и TAC Завершение, если файлы большие):

for file in file.log.*; do
    echo "file: $file"
    sed -n "
/[^[:space:]]/ {                # Match first non-whitespace line
    h                           # Copy to hold buffer
    s/^/first line: / p         # Add prefix and print
:loop
    $ {                         # Match last line
        g                       # Get contents of hold buffer
        s/^/last line: / p      # Add prefix and print
    }
    n                           # Load next line
    /[^[:space:]]/ h            # Copy non-whitespace line to hold buffer
    b loop                      # Jump back to process next line
}" "$file"
done
1
27.01.2020, 21:08
-

Что? Нет Perl?

for file in file.log.*; do 
    echo "FILE: $file"; 
    perl -ne 'if(/\S/){$k++; $l=$_}; 
              print "First line: $_" if $k==1; 
              END{print "Last line: $l\n"}' "$file";  
done

Объяснение

  • для файла в file.log.* : итерация по всем файлам, имена которых начинаются с file.log. в текущем каталоге и сохранить каждый из них как $file.
  • echo "FILE: $file"; : распечатайте имя файла.
  • perl -ne : читаем текущий входной файл построчно (-n), сохраняем каждую строку как специальную переменную Perl $_, и запускаем на ней скрипт, заданный -e.
  • if(/\S/){$k++; $l=$_} : если текущая строка соответствует небелому символу (\S), сохраните строку как $l и увеличьте счетчик $k на единицу.
  • выведите "First line: $_" if $k==1; : выведите текущую строку ($_) если $k равно 1. При этом будет выведена 1-я небелая строка.
  • END{выведите "Последняя строка: $l\n"} : это выполняется после того, как все входные строки будут прочитаны. Так как мы сохраняем каждую строку без пробелов как $l, то в конце файла $l будет последней строкой без пробелов. Таким образом, будет выведена последняя строка.

Другой подход:

for file in file.log.*; do 
    printf "FILE: %s\nFirst line: %s\nLast line: %s\n\n" \
        "$file" \
        "$(grep -Em 1 '\S' "$file")" \
        "$(tac "$file" | grep -Em1 '\S' )"; 
done

Объяснение

Это тот же самый цикл для только здесь мы используем printf для печати трех строк. Имя файла и вывод этих двух команд:

  • grep -Pm 1 '\S' "$file" : В команде -E активируются расширенные регулярные выражения, которые позволяют нам использовать \S для "не-белых пространств". -m1 означает "выход после первого найденного совпадения".
  • так "$file" | grep -Em1 '\S' : так обратная cat. Он выведет содержимое файла, но из последней строки в первую. Таким образом, эта команда выведет последнюю не белую строку.
2
27.01.2020, 21:08

команда awk:

awk -v OFS=: '
    FNR==1 {
        # the last non-blank line from the previous file
        if (line) {print filename, fnr, line}
        filename=FILENAME
        line=""
        p=0
    } 
    /^[[:blank:]]*$/ {next} 
    !p {
        # the first non-blank line
        print FILENAME, FNR, $0; p=1
    }
    {fnr=FNR; line=$0} 
    END {print filename, fnr, line}
' *

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

GNU awk v4 имеет шаблоны BEGINFILE и ENDFILE, которые значительно упрощают дело:

gawk -v OFS=: '
    BEGINFILE {p=0} 
    /^[[:blank:]]*$/ {next} 
    !p {print FILENAME, FNR, $0; p=1}
    {fnr=FNR; line=$0} 
    ENDFILE {print FILENAME, fnr, line}
' *
5
27.01.2020, 21:08
strm_1st_last() ( unset l i c n
l=1 i='i\\\\' c='c\\\\' n='\
';  eval "echo |sed -n \":b
    /[^[:blank:]]/h;$( wc -l "$@" | 
    sed -e '${1!d' -e "};s/[\"\/]/\\\\&/g
    s/^[ 0]*\([^ 0-9]\)/1$i$n empty: \1/;/\n/b
    s|^ *\([0-9]\{1,\}\) *\(.*\)|\\
    \$((1+(l+=\\1)-\\1)){$i$n\\2$n :l\\
         s/.*[^[:blank:]]/    \\&/p;//h;t\\
         n;\$((l-1)){ //bb$n//!$c$n\ALL BLANK$n};bl$n}\\
    \${l}{ x;s/^/    /p;s/.*//;x;d$n}|")"'" - "$@"'
)

Эта функция полагается на один процесс sed для создания работоспособного сценария за секунду. Что ж, он не просто полагается на sub-shell sed , но также и wc , чтобы сначала получить общие номера строк для каждого из своих аргументов, и сама оболочка для подсчета арифметических выражений sed строит как ссылки на строки для второго sed .

Обычно он обрабатывает все аргументы как единый поток. Например, если вы это сделаете:

seq 10 > file1; seq 5 > file2; sed -n \$= file[12]

sed напечатает ...

15

... потому что он автоматически объединяет все аргументы имени файла в единый поток данных. Так что мы просто работаем с этим.

Сначала wc запрашивается отчет обо всех их длинах, а затем sed переходит к работе, превращая его в работоспособный сценарий ввода на второй sed ].

Если wc сообщает, что в каком-либо из файлов есть 0 строк, sed напечатает пусто: имя файла для него и всех остальных прежде всего. (хотя, наверное, точнее было бы 0 строк).

Если при сканировании участка входных строк, который включает весь файл sed , вообще нет непустых символов, sed сообщит об этом ВСЕ ПУСТО (это единственный тип строкового отчета без отступа)

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

Итак, если я сделаю ...

strm_1st_last file[12]

file1
    1
    10
file2
    1
    5

или ...

: >file2; strm_1st_last file[12]

empty: file2
file1
    1
    10

... или ...

strm_1st_last ~/*.sh


empty: /home/mikeserv/alleq.sh
empty: /home/mikeserv/mansed5.sh
/home/mikeserv/chrome.sh
    #!/bin/bash
    ) &
/home/mikeserv/crap.sh
ALL BLANK

/home/mikeserv/getopts.sh
    c=$# t=\     l='
    done; printf '%s\n' "'${str#?}'"; done
/home/mikeserv/mansedmaybe.sh
    mansed () {
    );}
/home/mikeserv/mansed.sh
    mansed () {
    );}
/home/mikeserv/pr_after.sh
    pr_after() if       _i= _o=D OPTIND=1 _n='\
        fi
/home/mikeserv/script.sh
    #!/usr/bin/sh
    echo done
/home/mikeserv/serial.sh
    sq() ( IFS=\' set -f
    #   a               b
/home/mikeserv/your_config.sh
    zifs() { eval "shift ${3+3}
    )
/home/mikeserv/ytplay.sh
    ytplay() ( 
    )
/home/mikeserv/zifs.sh
    zifs() { eval "shift ${3+3}
    )
0
27.01.2020, 21:08

Попробуйте следующее:

for file in $(ls) ; do cat $file | sed -n '1p;$p' ; done
-1
27.01.2020, 21:08

Теги

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