Разное

Read bash file: Bash: Построчное Чтение Файла — While Read Line Цикл

Содержание

Bash: Построчное Чтение Файла — While Read Line Цикл

Цикл while — это лучший способ построчного чтения файла в Linux.

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

В этой статье я покажу общий синтаксис конструкции while read line в Bash и пример того, как построчно прочитать файл из командной строки в Linux.

Также я приведу пример Bash скрипта, который построчно читает передаваемый ему файл и выводит каждую строку, добавляя к ней определенный текст.

Дельный Совет: Сделайте Bash скрипт интерактивным! Научите его спрашивать «Да/Нет» для подтверждения. Читать далее →

Цикл While Read Line в Bash

Общая структура конструкции while read line, которая может использоваться в Bash скриптах:

while read LINE
    do COMMAND
done < FILE

Та же конструкция одной строкой (легко использовать из командной строки в Linux):

while read LINE; do COMMAND; done < FILE

В качестве примера выведем список всех пользователей из файла /etc/passwd:

$ while read LINE; do echo "$LINE" | cut -f1 -d":"; done < /etc/passwd
root
daemon
bin
[. ..]

LINE в этой конструкции — это название переменной, в которой сохраняется значение текущей строки во время каждой итерации цикла.

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

Например, если вы храните в файле список пользователей, будет лучше если вместо LINE вы назовете эту переменную USER, и тогда это будет выглядеть таким образом:

$ cat users.txt
Eric
Kyle
Stan
Kenny
$ while read USER; do echo "Привет $USER!"; done 

Дельный Совет: Выполняйте одну команду N раз подряд с помощью цикла FOR в Bash! Читать далее →

Bash Скрипт: Построчное Чтение Файла

Создадим Bash скрипт, который в качестве аргумента получает путь к файлу и печатает слова "Это строка:" в начали каждой строки этого файла.

Создайте пустой файл readfile.sh с помощью команды touch readfile. sh.

Сделайте его исполняемым с помощью chmod +x readfile.sh.

Откройте файл readfile.sh в текстовом редакторе и скопируем туда следующий код:

#!/bin/bash
FILE=$1
while read LINE; do
     echo "Это строка: $LINE"
done < $FILE

Дельный Совет: Не будьте занудой! Сделайте ваш Bash скрипты ЦВЕТНЫМ! Пусть он выглядит ВЕЛИКОЛЕПНО! Читать далее →

Сохраните изменения в запустите скрипт:

$ ./script.sh /etc/passwd
Это строка: root:x:0:0:root:/root:/bin/bash
Это строка: bin:x:1:1:bin:/bin:/sbin/nologin
Это строка: daemon:x:2:2:daemon:/sbin:/sbin/nologin
[...]

Команда read. Категория: ОС Linux • Сценарии


Общая форма этой команды выглядит следующим образом:

read [опции] переменная1 переменная2 …


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

  • Опция -t позволяет указать timeout в секундах, после которого команда отдаст управление назад в скрипт.
  • Опция -s скрывает ввод; это нужно для получения каких-то конфиденциальных данных, например пароля.
  • Опция -d указывает символ, при появлении которого чтение ввода нужно завершить; по умолчанию это символ переноса строки.
  • Опция -p строка показывает строку приглашения без оконечного перевода строки; обычно с помощью этой опции выводят подсказку, перед тем как команда будет считывать данные.


Если команде не было передано ни одной переменной, то ввод будет сохранен в переменную $REPLY.

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

while read line ; do
    команда1
    команда2
    ........
done < data.txt


В качестве примера выведем список всех пользователей из файла /etc/passwd:

$ while read line; do echo "$line" | cut -f1 -d:; done < /etc/passwd
root
daemon
bin
.....


Ниже приведен пример скрипта, который называется number и является упрощенной версией стандартной команды nl. Он принимает в качестве аргументов один или несколько файлов и отображает их содержимое в отдельно пронумерованных строках. Если же аргументы не заданы, скрипт читает данные из стандартного ввода.

#!/bin/bash
number=1

cat "$@" |
while read line ; do
    echo "$number: $line"
    ((number++))
done
$ cat linux.txt
Ubuntu
Redhat
Centos
Debian
Fedora
$ ./number linux.txt
1: Ubuntu
2: Redhat
3: Centos
4: Debian
5: Fedora
$ cat /etc/passwd | . /number 
1: root:x:0:0:root:/root:/bin/bash
2: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3: bin:x:2:2:bin:/bin:/usr/sbin/nologin
..........


И еще один скрипт, который представляет собой упрощенную версию команды cp:

#!/bin/bash
# Скрипт копирует файл из source в target; source может быть списком файлов, тогда target
# должен быть каталогом.

numargs=$#      # количество аргументов 
source_list=""  # список исходных файлов
copy_list=""    # список конечных файлов

#
# Обрабатываем аргументы, сохраняя в переменной source_list все, кроме последнего аргумента
#
while [ "$#" -gt 1 ] ; do
    source_list="$source_list $1"
    shift
done
target="$1"  # файл или директория

#
# Если количество аргументов меньше двух или количество аргументов больше двух, но последний
# аргумент не является каталогом, вывести сообщение об ошибке и завершить работу
#
if [ "$numargs" -lt 2 -o "$numargs" -gt 2 -a ! -d "$target" ] ; then
    echo "Использование: $0 file1 file2"
    echo "Или так: $0 file(s) dir"
    exit 1
fi

#
# Перебрать каждый файл в переменной source_list
#
for item in $source_list ; do
    # Выяснить, является ли целевой файл каталогом
    if [ -d "$target" ] ; then
        target_file="$target/$(basename $item)"
    else
        target_file="$target"
    fi
    
    # Добавить имя файла к переменной copy_list если файл еще не существует или если
    # пользователь дает разрешение на его перезапись
    if [ -e "$target_file" ] ; then
        echo -n "Файл $target_file уже существует.  Перезаписать (да/нет)?"
        read answer
        
        if [ "$answer" = "да" ] ; then
            copy_list="$copy_list $item"
        fi 
    else
        copy_list="$copy_list $item"
    fi
done

#
# Теперь проверяем, что список файлов для копирования не пустой, и можно копировать
#
if [ -n "$copy_list" ] ; then
    cp $copy_list $target
fi

Поиск:
$REPLY • Bash • CLI • Linux • read • stdin • Команда • Переменная

Как получить первую строку файла в bash script?

Вопрос:

Мне нужно вставить переменную bash в первую строку файла. Я думаю, что это с командой grep, но каким-либо образом можно ограничить количество строк?

Лучший ответ:

head берет первые строки из файла, а параметр -n может использоваться, чтобы указать, сколько строк должно быть извлечено:

line=$(head -n 1 filename)

Ответ №1

чтобы прочитать первую строку с помощью bash, используйте оператор read. например,

read -r firstline<file

firstline будет вашей переменной (нет необходимости назначать другому)

Ответ №2

line=$(head -1 file)

Будет работать нормально. (Как и предыдущий ответ). Но

line=$(read -r FIRSTLINE < filename)

будет немного быстрее, так как read — это встроенная команда bash.

Ответ №3

Этого достаточно и сохраняет первую строку filename в переменной $line:

read -r line < filename

Мне также нравится awk для этого:

awk 'NR==1 {print; exit}' file

Для сохранения самой строки используйте синтаксис var=$(command). В этом случае line=$(awk 'NR==1 {print; exit}' file).

Или даже sed:

sed -n '1p' file

С эквивалентом line=$(sed -n '1p' file).


См. образец при подаче read с помощью seq 10, то есть последовательности чисел от 1 до 10:

$ read -r line < <(seq 10)
$ echo "$line"
1

$ line=$(awk 'NR==1 {print; exit}' <(seq 10))
$ echo "$line"
1

Ответ №4

Вопрос не задавался вопросом, который является самым быстрым, но чтобы добавить к sed ответ, -n ‘1p’ плохо работает, поскольку пространство шаблонов все еще сканируется на больших файлах. Из любопытства я обнаружил, что «голова» выигрывает над седлом:

# best:
head -n1 $bigfile >/dev/null

# a bit slower than head (I saw about 10% difference):
sed '1q' $bigfile >/dev/null

# VERY slow:
sed -n '1p' $bigfile >/dev/null

Ответ №5

Просто echo первый список исходного файла в ваш целевой файл.

echo $(head -n 1 source.txt) > target.txt

Основы линукс: Введение в bash

О чем статья

Прочитав эту статью, вы узнаете что такое bash (стандартный командный интерпретатор линукс), научитесь обращаться со стандартными командами: ls, cp, mv… поймете назначение инодов, жестких и символических ссылок и многое другое.

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

Введение в bash

Shell

Если вы используете линукс, то знаете что после логина вас приветствует приглашение командного интерпретатора. Например такое:

\$

Если после логина загружается графическая оболочка, то чтобы добраться до командного интерпретатора нужно запустить эмулятор терминала (gnome-terminal, xfce4-terminal, konsole, xterm, rxvt…) или переключиться на один из виртуальных терминалов нажав CtrlAltF1 или CtrlAltF2 и т. д.

Приглашение командного интерпретатора на вашем компьютере может отличаться от того что показано в примере. Оно может содержать имя пользователя, имя компьютера и название текущей рабочей директории. Но несмотря на все эти различия, программа которая печатает это приглашение называется «shell» (оболочка), и скорее всего в роли вашей командной оболочки выступает программа которая называется bash.

У вас запущен bash?

Проверить запущен ли bash можно следующей командой:

\$ echo \$SHELL
/bin/bash

Если в результате выполнения этой команды вы получили ошибку или её вывод отличается от того что в примере, то возможно в вашей системе в качестве командной оболочки используется не bash. Несмотря на это, большая часть материала будет актуальна, но все же рекомендуем вам переключиться на bash. Сделать это можно (если bash установлен в системе) командой:

\$ bash

Что такое bash

Bash (акроним от «Bourne-again SHell») это стандартный интерпретатор команд на большинстве линукс систем. В его обязанности входит обработка и исполнение команд с помощью которых пользователь управляет компьютером. После того как вы завершили работу, можно завершить процесс командного интерпретатора. После нажатия клавиш CtrlD, команд exit или logout процесс командного интерпретатора будет завершен и на экране снова появится приглашение ввести имя пользователя и пароль.

Использование «cd»

Давайте начнем использовать bash для навигации по файловой системе. Для начала напечатайте следующую команду:

$ cd /

Этой командой мы указали bash-у что хотим переместиться в корневую директорию — /. Все директории в системе организованы в древовидную структуру и / это её начало (или корень). Команда cd служит для изменения текущей рабочей директории.

Пути

Чтобы узнать в каком месте файловой системы в данный момент вы находитесь (текущую рабочую директорию) наберите:

\$ pwd
/

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

Абсолютные пути

Вот несколько примеров абсолютных путей

/dev
/usr
/usr/bin
/usr/local/bin

Как вы уже могли заметить, все эти пути объединяет то, что они начинаются с /. Указывая путь /usr/local/bin в качестве аргумента команде cd мы говорим ей перейти в корневую директорию /, затем в директорию usr, потом в local и bin. Абсолютные пути всегда начинаются с /

Относительные пути

Второй вид путей называется относительными. Bash, команда cd и другие команды отсчитывают эти пути относительно текущей директории. Относительные пути никогда не начинаются с /. Например, если мы находимся в /usr

\$ cd /usr

Затем мы можем перейти в /usr/local/bin используя относительный путь

\$ cd local/bin
\$ pwd
/usr/local/bin

Использование «.

Относительные пути могут содержать одну или несколько директорий «..». «..» указывает на родительскую директорию по отношению к нашей рабочей директории. Пример:

\$ pwd
/usr/local/bin
\$ cd ..
\$ pwd
/usr/local

Как вы видите, команда cd .. ‘поднимает нас на уровень выше’.

Можно добавить .. к относительному пути. Это позволит переместиться в директорию, которая находится на одном уровне с той в которой мы находимся. Пример:

\$ pwd
/usr/local
\$ cd ../share
\$ pwd
/usr/share

Примеры с использованием относительных путей

Относительные пути могут быть довольно сложными. Вот несколько примеров. Результат выполнения команд не показан, попробуйте определить в какой директории вы окажетесь используя bash.

\$ cd /bin
\$ cd ../usr/share/zoneinfo

\$ cd /usr/X11R6/bin
\$ cd ../lib/X11

\$ cd /usr/bin
\$ cd . ./bin/../bin

Рабочая директория «.»

Перед тем как закончить разговор о команде cd, следует упомянуть еще несколько вещей. Во-первых, существует ещё одна специальная директория «.», которая указывает на текущую директорию. Эта директория используется для запуска исполняемых файлов, находящихся в текущей директории.

\$ ./myprog

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

cd и домашняя директория пользователя

Для того чтобы перейти в домашнюю директорию, нужно набрать

\$ cd

Без аргумента cd переместит вас в домашнюю директорию. Для суперпользователя домашней обычно является директория /root, а для обычных пользователей — /home/username/. Но что если мы хотим указать конкретный файл, находящийся в домашней директории. Например, как аргумент к программе ‘myprog’? Можно написать:

\$ ./myprog /home/user/myfile. txt

Однако, использовать абсолютные пути к файлам не всегда удобно. Эту же операцию можно сделать при помощи ~–тильды:

\$ ./myprog ~/myfile.txt

~ — специальное имя, указывающее в bash на домашнюю директорию пользователя.

Домашние директории других пользователей

Но что если нам нужно указать файл в домашней директории другого пользователя? Для этого после тильды нужно указать имя этого пользователя. Например, чтобы указать на файл fredsfile.txt находящийся в домашней директории пользователя fred:

\$ ./myprog ~fred/fredsfile.txt

Команды линукс

Введение в ls

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

\$ cd /usr
\$ ls
X11R6 doc i686-pc-linux-gnu lib man sbin ssl
bin gentoo-x86 include libexec portage share tmp
distfiles i686-linux info local portage. old src

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

\$ ls -a
. bin gentoo-x86 include libexec portage share tmp
.. distfiles i686-linux info local portage.old src
X11R6 doc i686-pc-linux-gnu lib man sbin ssl

Подробный список директорий

После самой команды ls в качестве ее аргумента можно указать один или более файлов или директорий. Если указать имя файла, то команда ls выведет информацию только об этом файле. А если указать название директории, ls покажет все ее содержимое. Опция ‘-l’ команды ls бывает очень полезной если вы хотите кроме имен файлов узнать более подробную информацию о них (права на файл, имя владельца, время последнего изменения файла и его размер).

В следующем примере показано применение опции ‘-l’ для вывода информации о файлах хранящихся в директории /usr

\$ ls -l /usr
drwxr-xr-x 7 root root 168 Nov 24 14:02 X11R6
drwxr-xr-x 2 root root 14576 Dec 27 08:56 bin
drwxr-xr-x 2 root root 8856 Dec 26 12:47 distfiles
lrwxrwxrwx 1 root root 9 Dec 22 20:57 doc -> share/doc
drwxr-xr-x 62 root root 1856 Dec 27 15:54 gentoo-x86
drwxr-xr-x 4 root root 152 Dec 12 23:10 i686-linux
drwxr-xr-x 4 root root 96 Nov 24 13:17 i686-pc-linux-gnu
drwxr-xr-x 54 root root 5992 Dec 24 22:30 include
lrwxrwxrwx 1 root root 10 Dec 22 20:57 info -> share/info
drwxr-xr-x 28 root root 13552 Dec 26 00:31 lib
drwxr-xr-x 3 root root 72 Nov 25 00:34 libexec
drwxr-xr-x 8 root root 240 Dec 22 20:57 local
lrwxrwxrwx 1 root root 9 Dec 22 20:57 man -> share/man
lrwxrwxrwx 1 root root 11 Dec 8 07:59 portage -> gentoo-x86/
drwxr-xr-x 60 root root 1864 Dec 8 07:55 portage. old
drwxr-xr-x 3 root root 3096 Dec 22 20:57 sbin
drwxr-xr-x 46 root root 1144 Dec 24 15:32 share
drwxr-xr-x 8 root root 328 Dec 26 00:07 src
drwxr-xr-x 6 root root 176 Nov 24 14:25 ssl
lrwxrwxrwx 1 root root 10 Dec 22 20:57 tmp -> ../var/tmp

В первой колонке показана информация о правах доступа к каждому файлу в списке. (Немного позже я объясню какая буква что обозначает) Следующая колонка показывает количество ссылок на каждый элемент списка. Третья и четвертая колонки — владелец и группа файла соответственно. Пятая колонка — размер. Шестая — время последнего изменения файла (‘last modified time’ или mtime). Последняя колонка — имя файла или директории (Если это ссылка, то после знака ‘–>‘ стоит имя объекта на который она ссылается).

Как посмотреть только директории

Иногда возникает потребность посмотреть информацию только о директориях, а не о всем их содержимом. С этой задачей поможет справиться опция ‘-d’, которая указывает команде выводить информацию только о директориях. Пример:

\$ ls -dl /usr /usr/bin /usr/X11R6/bin ../share
drwxr-xr-x 4 root root 96 Dec 18 18:17 ../share
drwxr-xr-x 17 root root 576 Dec 24 09:03 /usr
drwxr-xr-x 2 root root 3192 Dec 26 12:52 /usr/X11R6/bin
drwxr-xr-x 2 root root 14576 Dec 27 08:56 /usr/bin

Рекурсивный список и информация о инодах

Действие опции ‘-R’ противоположно действию ‘-d’. Она позволяет выводить информацию о файлах находящихся в директории рекурсивно. Сначала показывается содержимое директории верхнего уровня, потом по очереди содержимое всех поддиректорий и так далее. Вывод этой команды может быть достаточно объемным, поэтому мы не приводим ее пример, но вы можете попробовать сделать это самостоятельно, набрав в командной строке ‘ls -R‘ или ‘ls -Rl‘.

И, наконец, опция ‘-i’ используется для вывода инодов каждого объекта файловой системы.

\$ ls -i /usr
1409 X11R6 314258 i686-linux 43090 libexec 13394 sbin
1417 bin 1513 i686-pc-linux-gnu 5120 local 13408 share
8316 distfiles 1517 include 776 man 23779 src
43 doc 1386 info 93892 portage 36737 ssl
70744 gentoo-x86 1585 lib 5132 portage.old 784 tmp

Что такое иноды?

Каждый объект файловой системы (файл, директория…) имеет свой уникальный номер, называемый инодом (inode number). Эта информация может показаться незначительной, но понимание функции инодов поможет вам разобраться во многих операциях над файловой системой. Например, посмотрим на «.» и «..» как на ссылки, присутствующие в каждой директории. Чтобы понять что из себя представляет директория «., узнаем инод директории /use/local

\$ ls -id /usr/local
5120 /usr/local

Как можем видеть, инод директории /usr/local — 5120. Теперь посмотрим какой инод у директории /usr/local/bin/..:

\$ ls -id /usr/local/bin/..
5120 /usr/local/bin/..

Получается, что иноды директорий /usr/local и /usr/local/bin/.. совпадают! Это значит, что на инод 5120 ссылаются два имени: /usr/local и /usr/local/bin/.. То есть это два разных имени одной директории. Каждый инод указывает на определенное место на диске.

С каждым инодом может быть связано несколько имен объектов файловой системы. Количество ‘синонимов’ файла (объектов файловой системы, ссылающихся на один инод) показывает число во втором столбце вывода команды ‘ls -l‘.

\$ ls -dl /usr/local
drwxr-xr-x 8 root root 240 Dec 22 20:57 /usr/local

На этом примере видно (второй столбец), что на директорию /usr/local ссылаются 8 разных объектов файловой системы. Вот их имена:

/usr/local
/usr/local/.
/usr/local/bin/..
/usr/local/games/..
/usr/local/lib/..
/usr/local/sbin/..
/usr/local/share/..
/usr/local/src/..

mkdir

Давайте рассмотрим команду mkdir. Она служит для создания новых директорий. В следующем примере демонстрируется создание трех новых директорий (tic, tac, toe) в директории /tmp

\$ cd /tmp
$ mkdir tic tac toe

По умолчанию команда mkdir не может создать вложенной структуры директорий. Поэтому, если вам нужно создать несколько вложенных одна в другую директорий (won/der/ful), то вам придется три раза поочередно вызывать эту команду:

\$ mkdir won/der/ful
mkdir: cannot create directory 'won/der/ful': No such file or directory
\$ mkdir won
\$ mkdir won/der
\$ mkdir won/der/ful

Упростить эту операцию можно добавив опцию ‘-p’ к команде mkdir. Эта опция позволяет создавать вложенную структуру директорий:

\$ mkdir -p easy/as/pie

Чтобы узнать о возможностях этой утилиты подробнее, прочитайте справку, которая вызывается командой man mkdir. Справки есть практически ко всем командам из этого руководства (например man ls), кроме cd, т.к. она встроена в bash (для таких команд справка вызывается так: help cd)

touch

Перейдем к изучению команд cp и mv, служащих для копирования, переименования и перемещения файлов и директорий. Но перед этим создадим пустой файл в директории /tmp при помощи команды touch:

\$ cd /tmp
\$ touch copyme

Команда touch обновляет время последнего доступа к файлу (шестая колонка вывода команды ls -l) если он уже существует или создает новый пустой файл, если его ещё нету. После этой операции у нас должен появиться пустой файл /tmp/copyme.

echo

Теперь, когда у нас есть пустой файл, запишем в него текстовую строку при помощи команды echo, которая выводит переданный ей аргумент на стандартное устройство вывода (текстовый терминал в нашем случае).

\$ echo "firstfile"
firstfile

Чтобы записать строку в наш файл, перенаправим в него вывод команды echo:

\$ echo "firstfile" > copyme

Знак > (больше) указывает командной оболочке что нужно перенаправить вывод команды стоящей слева в файл, имя которого находится справа. Если файла с таким именем не существует, он будет создан автоматически. А если такой файл уже есть, то он будет перезаписан (все его содержимое будет стерто перед записью нашей строки). Команда ‘ls -l’ покажет что размер нашего файла теперь равен 10 байтам — девять байт занимает слово ‘firstfile’ и один байт символ перевода строки.

\$ ls -l copyme
-rw-r--r-- 1 root root 10 Dec 28 14:13 copyme

cat и cp

Для вывода содержимого файла на терминал используется команда cat:

\$ cat copyme
firstfile

Теперь мы можем приступить к разбору базовой функциональности команды cp. Эта команда принимает два аргумента. Первый — имя уже существующего файла (‘copyme’), второй — название новой копии, которую мы хотим сделать (‘copiedme’).

\$ cp copyme copiedme

Можем убедиться, что новая копия файла имеет другой номер инода (это значит что мы получили действительно новый отдельный файл, а не просто ссылку на старый)

\$ ls -i copyme copiedme
648284 copiedme 650704 copyme

mv

Теперь применим команду mv чтобы переименовать файл («copiedme» –> «movedme»). Номер инода после этой операции не меняется, а изменяется только название файла.

\$ mv copiedme movedme
\$ ls -i movedme
648284 movedme

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

Команда mv позволяет не только переименовывать файлы, но и перемещать их. Например, чтобы переместить файл /var/tmp/myfile.txt в директорию /home/user нужно дать команду:

\$ mv /var/tmp/myfile.txt /home/user

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

Нужно заметить, существует вероятность, что новый присвоенный номер инода может совпасть со старым, но она чрезвычайно мала.

Чтобы переместить одновременно несколько файлов в одну директорию нужно написать:

\$ mv /var/tmp/myfile1.txt /var/tmp/myfile2.txt /home/user

или

\$ mv -t /home/user /var/tmp/myfile1.txt /var/tmp/myfile2.txt

Если добавить опцию ‘-v’, на экран будет выведен отчет о проделанной операции:

\$ mv -vt /home/user /var/tmp/myfile1.txt /var/tmp/myfile2.txt
'/var/tmp/myfile1.txt' -> '/home/user/myfile1.txt'
'/var/tmp/myfile2.txt' -> '/home/user/myfile2.txt'

📜 Bash скрипт для копирования всех файлов с той же структурой каталогов – Information Security Squad

Этот скрипт оболочки предназначен для конкретной задачи, необходимой для нашего сервера.

Задача

Наша задача – скопировать все файлы, созданные в каталоге, в другой каталог с такой же структурой каталогов.

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

Скрипт должен поддерживать ту же структуру каталогов в каталоге назначения.

После этого он изменит права в каталоге назначения.

После успешного копирования файла скрипт должен удалить файлы из исходного каталога.

Shell скрипт резервного копирования Linux

Создайте скрипт оболочки в вашей системе и добавьте содержимое, показанное ниже.

Обновите исходные и целевые каталоги в нужном месте.

После сохраенения не забудьте сделать скрипт исполняемым:

chmod +x script.sh

#!/bin/bash

##################### переменные #############################

### Установите правильное местоположение источника и места назначения
SOURCE_DIR="/source/dir/"
DEST_DIR="/desination/dir/"
TMP_FILE=/tmp/copyfileslist.txt

### Установите имя пользователя и имя группы, чтобы установить права на скопированные файлы
### Установите для CHANGE_OWNERSHIP значение 1, чтобы изменить владельца, или 0, чтобы не изменять его. 
CHANGE_OWNERSHIP=1
USER='root'
GROUP='root'


########### Не редактируйте, пока не потребуется #################

### Проверка, существует ли исходный каталог
### Скрипт остановится, если источника не существует

if [ -d "${SOURCE_DIR}" ]; then
echo "Source directory found"
else
echo "Source directory not found. Please check above variables are set correctly"
echo "script exited"
exit 1
fi

### Проверка, существует ли каталог назначения
### Скрипт создаст каталог назначения, если он не существует.
### Если не удалось создать каталог, скрипт будет прерван

if [ -d "${DEST_DIR}" ]; then
echo "Destination directory found, all ok"
else
echo "Destination directory not found, creating now"
mkdir -p "${DEST_DIR}"
if [ $? -eq 0 ]; then
echo "Successfully created destination directory."
else
echo "Failed to create destination directory.  Script exited"
exit 1
fi
fi


### Копирование всех файлов, доступных в исходном каталоге
### После успешного копирования файла скрипт удалит их из исходного каталога.
cd "${SOURCE_DIR}"

if [ $? -eq 0 ]; then
find . -type f > ${TMP_FILE}

while read CURRENT_FILE_NAME
do
cp --parents "${CURRENT_FILE_NAME}" "${DEST_DIR}"
if [ $? -eq 0 ]; then
echo "File ${CURRENT_FILE_NAME} successfully copied."
rm -f "${CURRENT_FILE_NAME}"
else
echo "File ${CURRENT_FILE_NAME} failed to copy"
fi
done < ${TMP_FILE}
rm -f ${TMP_FILE}
fi

## Установка прав на новые файлы

if [ ${CHANGE_OWNERSHIP} -eq 1 ]; then
sudo chmod 775 -R "${DEST_DIR}"
sudo chown ${USER}:${GROUP} -R "${DEST_DIR}"
fi

################### Конец скрипта ###################################


Специальные параметры bash с примерами

Сейчас пойдет речь о таких параметрах bash как $, $@, $#, $$, $!, $?, $-, $
Для доступа ко всему списку позиционных параметров доступны два специальных параметра $* и $@. За двойными кавычками они оба эквивалентны, оба раскрывают список позиционных параметров, начиная с $1, разделенные пробелами.

В двойных кавычках, однако, они различаются:

  • $* в паре двойных кавычек эквивалентен списку позиционных параметров, разделенных первым символом IFS «$1C$2c$3…».
  • $@ в паре двойных кавычек эквивалентен списку позиционных параметров, разделенных пробелами без кавычек, т. е., «$1» «$2″..»$Н.»

Пример 1: Используем Bash $* и $@ для расширения позиционных параметров

В этом примере будут показаны значения, доступны в $* и $@.
Создадим скрипт expan:

#!/bin/bash

export IFS='-'

cnt=1

# Printing the data available in $*
echo "Values of \"\$*\":"
for arg in "$*"
do
  echo "Arg #$cnt= $arg"
  let "cnt+=1"
done

cnt=1

# Printing the data available in $@
echo "Values of \"\$@\":"
for arg in "$@"
do
  echo "Arg #$cnt= $arg"
  let "cnt+=1"
done

Затем, выполним этот скрипт, как указано ниже, чтоб увидеть, как $* и $@ работают.

#./expan.sh "This is" 2 3
Values of "$*":
Arg #1= This is-2-3
Values of "$@":
Arg #1= This is
Arg #2= 2
Arg #3= 3
  • Вышеприведенный скрипт экспортировал значение IFS (внутренний разделитель полей) с помощью ‘-‘.
  • В скрипт передается три параметра $1=»This is», $2=» 2″и $ 3 = «3».
  • При печати каждого значения специального параметра «$*», он дает только одно значение, которое является целым позиционным параметром, разделенных IFS.
  • В то время как «$@» дает вам каждый параметр как отдельное слово.

Пример 2: Используем $# для подсчета позиционных параметров

$# — специальный параметр в bash, который дает число позиционных параметров в десятичном формате.
Создадим следующий скрипт:

#!/bin/bash

if [ $# -lt 2 ]
then
  echo "Usage: $0 arg1 arg2"
  exit
fi

echo -e  "\$1=$1"
echo -e "\$2=$2"

let add=$1+$2
let sub=$1-$2
let mul=$1*$2
let div=$1/$2

echo -e "Addition=$add\nSubtraction=$sub\nMultiplication=$mul\nDivision=$div\n"

Если число позиционных параметров меньше 2, то скрипт вызовет информацию об использовании:

# . /arithmetic.sh 33
Usage: ./arithmetic.sh arg1 arg2

Пример 3: Параметры процесса — $$ и $!

Специальный параметр $$ выдаст PID шелла. $! дает идентификатор процесса последнего выполненного фонового процесса.

Следующий скрипт печатает идентификатор процесса оболочки и идентификатор последнего выполнения фонового процесса.

#!/bin/bash

echo -e "Process ID=$$"

sleep 1000 &

echo -e "Background Process ID=$!"

Теперь выполним скрипт и проверим PID, который будет выведен.

# ./proc.sh
Process ID=16007
Background Process ID=16008
# ps
  PID TTY          TIME CMD
15798 pts/0    00:00:00 bash
16008 pts/0    00:00:00 sleep
16010 pts/0    00:00:00 ps

Пример 4: Другие специальные параметры Bash -$?, $-, $_

  • $? Дает статус выхода последней выполненной команды.
  • $- Параметры, заданные с помощью встроенной команды Set
  • $_ Дает последний аргумент предыдущей команды. При запуске оболочки выдает абсолютное имя файла скрипта шелла, который выполняется.

Рассмотрим следующий скрипт:

#!/bin/bash

echo -e "$_"; ## Absolute name of the file which is being executed

/usr/bin/uname  # execute the command.
#check the exit status of dbhome
if [ "$?" -ne "0" ]; then
  echo "Sorry, Command execution failed !"
fi

echo -e "$-"; #Set options - hB

echo -e $_  # Last argument of the previous command.

В приведенном выше скрипте, последнее предложение «echo -e $» ($нижнее_подчеркивание), а также выведет hB, которое является значением последнего аргумента предыдущей команды. Итак, $ даст значение после расширения

# ./others.sh
./others.sh
Linux
hB
hB

Источник http://www.thegeekstuff.com/2010/05/bash-shell-special-parameters/

Bash Прочитать файл построчно

Bash Прочитать файл построчно

Чтобы прочитать файл построчно в сценариях Bash, ниже приведены некоторые из способов, подробно объясненных.

Пример — использование цикла while

Ниже приводится синтаксис чтения файла построчно в Bash с использованием цикла bash while:

Синтаксис

строка при чтении; do

# строка доступна для обработки

echo $ line

done

Входной файл

sampleFile. txt

Изучите сценарии Bash.

Добро пожаловать в TutorialKart!

Изучите Bash на примерах.

Файл сценария Bash

файл для чтения построчно

#! / Bin / sh

i = 1

при чтении строки ; do

# строка доступна для обработки

echo Line $ i: $ line

i = $ ((i + 1))

done

Вывод сценария Bash — Терминал

~ / workspace / bash / file $ ./read-file-line-by-line

Строка 1: Изучение сценариев Bash.

Строка 2: Добро пожаловать в TutorialKart!

Строка 3: Изучите Bash на примерах.

Пример — предотвращение экранирования обратной косой черты

Чтобы предотвратить экранирование обратной косой черты при чтении файла построчно в bash, используйте опцию -r для команды read :

Синтаксис

34

при чтении строки -r; do

# строка доступна для обработки

echo $ line

done

Bash Script File

read-file-line-by-line

# ! / bin / sh

i = 1

при чтении -r строка; do

# строка доступна для обработки

echo Line $ i: $ line

i = $ ((i + 1))

done txt

Вывод сценария Bash — Терминал

~ / workspace / bash / file $ ./read-file-line-by-line

Строка 1: Изучение сценариев Bash.

Строка 2: Добро пожаловать в TutorialKart!

Строка 3: Изучите Bash на примерах.

Пример — предотвращение обрезки начальных или конечных пробелов.

Чтобы предотвратить обрезку начальных или конечных пробелов при чтении файла построчно в bash, используйте команду IFS в сочетании с командой read :

Синтаксис

в то время как IFS = строка чтения ; do

# строка доступна для обработки

echo $ line

done

Bash Script File

read-file-line-by-line

# ! / bin / sh

i = 1

, а IFS = строка чтения; do

# строка доступна для обработки

echo Line $ i: $ line

i = $ ((i + 1))

done txt

Вывод сценария Bash — Терминал

~ / workspace / bash / file $ ./read-file-line-by-line

Строка 1: Изучение сценариев Bash.

Строка 2: Добро пожаловать в TutorialKart!

Строка 3: Изучите Bash на примерах.

Заключение:

В этом руководстве по Bash мы научились читать файл построчно в сценариях bash с примерами.

Bash Script — Проверить, доступен ли файл для чтения

Bash Script, чтобы проверить, есть ли у файла разрешения на чтение

Чтобы проверить, доступен ли файл для чтения, другими словами, если файл имеет права на чтение, с помощью сценария bash, используйте [-r FILE] с оператором bash if.

Синтаксис

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

где ФАЙЛ — это путь к файлу, права доступа которого нам нужно проверить.

Выражение возвращает истину, если файл имеет разрешение на чтение, и ложь, если у файла нет разрешений на чтение.

Ниже приводится список примеров, которые демонстрируют нам, как проверить, доступен ли файл для чтения или нет.

  • Пример 1 — Простой оператор if для проверки, доступен ли файл для чтения
  • Пример 2 — Проверить, является ли аргумент, переданный функции, файлом и доступен для чтения

Для примеров в этом руководстве мы будем использовать два файла, показанные ниже:

arjun @ arjun-VPCEh36EN: / home / tutorialkart $ ls -lr

всего 125016

—w ——- 1 корневой корень 12 октября 5 09:35 пример.txt

-rwxr — r— 1 root root 20 октября 5 15:33 dummy.txt

Если вы соблюдаете разрешения для этих файлов,

  • sample.txt не читает разрешения.
  • dummy.txt имеет разрешения на чтение для всех пользователей.

Пример 1 — Проверить, доступен ли файл для чтения

В следующем примере мы будем использовать выражение -r и проверять, доступен ли указанный файл для чтения. Мы используем выражение в инструкции bash if else.

Файл сценария Bash

bash-script-if-file-is-readable

4

Запустить

#! / Bin / bash

# Сценарий — Файл существует и доступен для чтения

if [-r /home/tutorialkart/dummy.txt];

, затем

echo «/home/tutorialkart/dummy.txt доступен для чтения»

else

echo «/home/tutorialkart/dummy.txt не читается»

fi

# Файл существует и сценарий не читается

, если [-r / home / tutorialkart / sample.текст ];

, затем

echo «/home/tutorialkart/sample.txt доступен для чтения»

else

echo «/home/tutorialkart/sample.txt не читается»

fi

0

script в Терминале, и вы увидите следующий вывод, если у вас есть файлы, упомянутые в вашей системе.

Вывод

Программный вывод

arjun @ arjun-VPCEh36EN: ~ / workspace / bash $. / bash-script-if-file-readable

/home/tutorialkart/dummy.txt доступен для чтения

/home/tutorialkart/sample.txt не читается

Пример 2 — Проверить, если аргумент, переданный функции, является файлом и доступен для чтения

В этом примере мы напишем функцию, первый аргумент которой — путь к файлу. А в функции мы проверим, доступен ли переданный аргумент (ФАЙЛ) для чтения или нет.

Файл сценария Bash

bash-script-if-file-is-readable-2

#! / Bin / bash

# функция для проверки возможности чтения переданного аргумента

checkIfReadable () {

# $ 1 означает первый аргумент

if [-r «$ 1»];

, затем

echo «$ 1 можно прочитать.»

else

echo» $ 1 не читается. «

fi

}

# Сценарий — файл существует и доступен для чтения

checkIfReadable» /home/tutorialkart/dummy. txt4 «

Сценарий — Файл существует и не читается

checkIfReadable «/home/tutorialkart/sample.txt»

Запустите приведенный выше сценарий, и вы получите следующий результат.

Выход

Выход программы

arjun @ arjun-VPCEh36EN: ~ / workspace / bash $./ bash-script-if-file-is-readable-2

/home/tutorialkart/dummy.txt доступен для чтения.

/home/tutorialkart/sample.txt не читается.

Заключение

В этом руководстве по Bash мы узнали, как проверить, имеет ли указанный файл права на чтение или нет.

Bash: чтение файла построчно — цикл при чтении строки

Цикл и — лучший способ построчно читать файл в Linux.

Если вам нужно прочитать файл построчно и выполнить какое-либо действие с каждой строкой — тогда вам следует использовать конструкцию while read line в Bash, так как это наиболее правильный способ сделать необходимое.

В этой статье я покажу общий синтаксис конструкции при чтении строки в Bash и пример того, как читать файл построчно из командной строки Linux.

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

Дельный Совет: Сделайте ваш Bash-скрипт интерактивным! Научите его запрашивать подтверждение «Да / Нет». Узнать больше →

Цикл при чтении строки в Bash

Общая конструкция при чтении строки , которая может использоваться в сценариях Bash:

 при чтении LINE
    сделать КОМАНДУ
сделано <ФАЙЛ 

Такая же конструкция в одной строке (удобна для использования в командной строке Linux):

 при чтении СТРОКА; сделать КОМАНДУ; сделано <ФАЙЛ 

В качестве примера позволяет распечатать всех пользователей из файла / etc / passwd :

 $ при чтении LINE; сделать эхо "$ LINE" | вырезать -f1 -d ":"; сделано  ..]
 

СТРОКА в этой конструкции - это имя переменной, которая хранит строку во время каждой итерации цикла.

Вы можете изменить его на более подходящее имя, в зависимости от содержимого ФАЙЛА .

Например, если вы храните список пользователей в ФАЙЛЕ - лучше назвать эту переменную не LINE , а USER , как показано ниже:

 $ cat users.txt
Эрик
Кайл
Стэн
Кенни 
 $ при чтении USER; do echo "Hello $ USER!"; сделанный
 

Дельный Совет: Напишите команду один раз и выполните ее N раз, используя цикл Bash FOR ! Узнать больше →

Bash Script: чтение файла построчно

Давайте создадим сценарий Bash, который принимает путь к файлу в качестве аргумента и печатает «Это строка:» перед каждой строкой этого файла.
Создайте пустой файл readfile.sh с помощью команды touch readfile.sh .

Сделайте его исполняемым с помощью chmod + x readfile. sh .

Откройте файл readfile.sh в текстовом редакторе и введите следующий код:

 #! / Bin / bash
ФАЙЛ = $ 1
пока читал LINE; делать
     echo "Это строка: $ LINE"
выполнено <$ FILE 

Дельный Совет: Не будьте занудой! Добавьте ЦВЕТА в свой сценарий Bash! Сделайте это УДИВИТЕЛЬНО! Узнать больше →

Сохраните и выполните сценарий:

 $./script.sh / etc / passwd
Это строка: root: x: 0: 0: root: / root: / bin / bash
Это строка: bin: x: 1: 1: bin: / bin: / sbin / nologin
Это строка: daemon: x: 2: 2: daemon: / sbin: / sbin / nologin
[...] 

Bash: проверить, существует ли файл

При создании сценария bash обычно полезно проверить, существует ли файл , прежде чем пытаться выполнить с ним какое-либо действие.

Это задание для команды test , которая позволяет проверять, существует ли файл и какого он типа.

Поскольку выполняется только проверка - команда test устанавливает код выхода на 0 ( ИСТИНА ) или 1 ( FALSE ), независимо от того, успешно или нет.

Также команда test имеет логический оператор «не», который позволяет получить ответ TRUE , когда ему нужно проверить , если файл не существует .

Дельный Совет: Создайте умный сценарий bash ! Сделайте больше тестов! Легко проверьте, существует ли строка в файле! Узнать больше →

Оболочка Bash: проверьте, существует ли файл

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

 $ test -f ИМЯ ФАЙЛА 

- или -

 $ [-f ИМЯ ФАЙЛА] 

Проверить, существует ли файл / etc / passwd ( ИСТИНА ):

 $ тест -f / etc / passwd
$ echo $?
0

$ [-f / etc / passwd]
$ echo $?
0 

Проверить, существует ли файл / etc / bebebe ( FALSE ):

 $ тест -f / etc / bebebe
$ echo $?
1

$ [-f / etc / bebebe]
$ echo $?
1 

Проверить, не существует ли файл / etc / bebebe ( TRUE ):

 $ тест! -f / и т.  д. / bebebe
$ echo $?
0

$ [! -f / etc / bebebe]
$ echo $?
0 

Если файл существует, то…

Само собой разумеется, что мы не просто проверяем, существует ли файл без причины.

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

Может быть, если файла нет - нет смысла двигаться дальше и требуется сломать скрипт или что-то еще.

В приведенных ниже примерах позволяет распечатать соответствующие сообщения в зависимости от результатов команды test .

Дельный Совет: Оператор CASE - это простейшая форма оператора IF-THEN-ELSE ! Если у вас много элементов ELIF - лучше использовать CASE ! Узнать больше →

Проверить, существует ли файл / etc / passwd и распечатать сообщение, если он ИСТИНА :

 $ если [-f "/ etc / passwd"]; затем эхо «Файл существует»; фи
Файл существует 

Проверить, не существует ли файл / etc / bebebe , и распечатать сообщение, если он ИСТИНА :

 $ если [! -f "/ etc / bebebe"]; затем эхо «Файл не существует»; фи
Файл не существует 

Проверить, существует ли файл, и в каждом случае распечатать соответствующее сообщение:

 $ [-f "/ etc / passwd"] && echo "Файл существует" || echo "Файл не существует"
Файл существует
$ [-f "/ etc / bebebe"] && echo "Файл существует" || echo "Файл не существует"
Файл не существует 

Bash Script: проверьте, существует ли файл

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

Создайте пустой файл checkfile.sh с помощью команды touch checkfile.sh .

Сделайте его исполняемым с помощью chmod + x checkfile.sh .

Откройте файл checkfile.sh с помощью текстового редактора и введите следующий код:

 #! / Bin / bash
ФАЙЛ = $ 1
если [-f $ FILE]; тогда
   echo "Файл" $ FILE "существует."
еще
   echo "Файл '$ FILE' не найден."
fi 

Дельный Совет: Хороший сценарий bash печатает использование и завершает работу, если аргументы не указаны! Настроить очень просто! Узнать больше →

Сохраните и выполните сценарий следующим образом:

 $./checkfile.sh / etc / bebebe
Файл "/ etc / bebebe" не найден.
$ ./script.sh / etc / passwd
Файл "/ etc / passwd" существует. 

Проверить, существует ли файл и есть ли он…

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

Вот еще несколько полезных опций, которые могут помочь проверить, существует ли «файл» и имеет ли он определенные разрешения или это символическая ссылка , сокет или каталог :

Опция Описание
-e Проверить, существует ли файл, независимо от типа (каталог, сокет и т. Д.).)
-f Проверить, существует ли файл и является ли он обычным файлом
-r Проверить, существует ли файл и предоставлено ли разрешение на чтение
-w Проверить, существует ли файл и предоставлено ли разрешение на запись
Проверить, существует ли файл и предоставлено разрешение на выполнение
-L Проверить, существует ли файл и является ли он символической ссылкой
-S Проверить, существует ли файл и является ли он сокетом
-d Проверить, существует ли каталог

Запустите man test , чтобы увидеть всех доступных операторов.

bash: чтение файла в массив

Учитывая список стран, каждая в новой строке,
ваша задача - прочитать их в массив, а затем отобразить элемент с индексом 3.
Обратите внимание, что индексация начинается с 0.

Пример ввода :

  Намибия
Науру
Непал
Нидерланды
Новая Зеландия
Никарагуа
Нигер
Нигерия
Северная Корея
Норвегия
  

Пример вывода :

Этот вопрос взят из http: // hackerrank.com вызов опубликован
Вот.

bash 4 представил readarray (также известный как mapfile ), который позволяет вам делать:

  readarray -t стран
echo "$ {страны [3]}"
  

Я предполагаю, что это не то, что имел в виду автор задания, поэтому остальная часть этой статьи
обсуждает, как было бы «нормально» реализовано, например, используя цикл при чтении .

Итак, во-первых, что такое массив? Итак, у вас есть «нормальная» переменная, имеющая одно значение.Массив похож на список тем, что может содержать несколько значений.

  нормальный = переменный
массив = (а б в)
  

В целях форматирования мы возьмем только несколько стран из входных данных примера.

  $ cat пример ввода
Намибия
Науру
Непал
Нидерланды
$ пока читал страну; сделать страны + = ($ страна); done <ввод-образец
$ declare -p страны
декларировать -a countries = '([0] = "Намибия" [1] = "Науру" [2] = "Непал" [3] = "Нидерланды")'
$ echo $ {страны [3]}
Нидерланды
  

Итак, read country считывает строку ввода из stdin и сохраняет ее в переменной
страна ., а означает, что он будет перебирать все строки в stdin.

Переменные не требуют предварительного объявления. Вы можете добавить к несуществующей переменной и
это «Просто работает» .

  $ s + = foo
$ s + = бар
$ declare -p s
объявить - s = "foobar"
  

Итак, s изначально не существовал, а s + = foo сделал то же самое, что и s = foo в этом случае, поскольку
он добавлял foo ни к чему. По умолчанию переменные обрабатываются как «строки», поэтому
s + = bar затем добавляет строку bar к существующему значению foo , давая нам foobar .

Однако в нашем коде стран + = () . () здесь заставляет переменную обрабатывать
как массив, а не строка. Когда вы добавляете в массив, он добавляет новый элемент в конец
массива.

  $ s + = (баз)
$ declare -p s
объявить -a s = '([0] = "foobar" [1] = "baz")'
  

- перенаправление файла. Он отправляет содержимое файла sample-input в
стандартный ввод. Кстати, для перенаправления stdout в файл вы можете использовать > output-file

И, наконец, мы используем declare -p , чтобы получить как «вывод отладки» .
переменной.

Итак, давайте заменим Nepal на New Zealand в нашем примере ввода. Примечание , что мы
также добавляются в пробел, в отличие от данного примера ввода.

  $ cat пример ввода
Намибия
Науру
Новая Зеландия
Нидерланды
$ страны = ()
$ пока читал страну; сделать страны + = ($ страна); done <ввод-образец
$ declare -p страны
декларировать -a countries = '([0] = "Намибия" [1] = "Науру" [2] = "Новый" [3] = "Зеландия" [4] = "Нидерланды")'
  

стран = () устанавливает стран обратно как пустой массив, удаляя содержимое из
наш предыдущий пробег.

У нас теперь 5 стран вместо 4. WTF происходит, пожалуйста?

  $ страна = Новая Зеландия
bash: Зеландия: команда не найдена
  

При синтаксическом анализе bash разбивает все на «слов» - так что здесь у нас есть 2 слова: страна = Новый и Зеландия .
Это не то поведение, которое нам нужно, поэтому мы можем использовать одно из следующего:

  $ country = 'Новая Зеландия'
$ country = "Новая Зеландия"
$ country = Новая \ Зеландия
  

Разница между одинарными и двойными кавычками заключается в том, что переменные внутри двойных кавычек заменяются.
по их ценностям.(Вы можете увидеть, что это называется «расширение» .)

  $ name = Карл
$ echo "Меня зовут: $ name"
Меня зовут: Карл
$ echo 'Меня зовут: $ name'
Меня зовут: $ name
  

Но мы используем читать , чтобы сохранить значение в стране , так что это не наша проблема? Ну да, проблема в том
с странами + = ($ страна)

Мы будем использовать set -x , который включит отладочную информацию о том, как bash выполняет наши команды. комплект + x
можно использовать, чтобы выключить его.

  $ набор -x
$ echo $ country
+ эхо Новой Зеландии
Новая Зеландия
$ echo "$ country"
+ эхо "Новая Зеландия"
Новая Зеландия
  

Итак, когда мы использовали двойные кавычки около $ country bash выполнил echo 'New Zealand' , т.е.
обрабатывает значение $ страна как одно слово. Без двойных кавычек значение
$ страна разбита на несколько слов.

Другой пример:

  $ args () {echo $ #; }
$ args $ страна
2
$ args "$ страна"
1
  

Итак, здесь мы определяем функцию оболочки args , которая просто выводит $ # , то есть количество переданных аргументов.Как видите, из-за отсутствия двойных кавычек произошло разделение слов, и мы передали 2 аргумента
вместо 1.

Это одна из причин, по которой вы увидите, что "$ var" используется вместо $ var .

Хорошо, поэтому мы хотим, чтобы $ country обрабатывались как одно слово, поэтому мы должны заключить его в двойные кавычки:

  $ стран = ()
$ пока читал страну; сделать страны + = ("$ страна"); done <ввод-образец
$ declare -p страны
декларировать -a countries = '([0] = "Намибия" [1] = "Науру" [2] = "Новая Зеландия" [3] = "Нидерланды")'
$ echo $ {страны [3]}
Нидерланды
  

Нет никаких цитат вокруг $ {стран [3]} , но в данном случае это не имело значения.Однако, помимо проблемы с разделением слов, может возникнуть еще одна проблема, если значение вашего
переменная содержит подстановки символов:

  $ ls
ввод образца
$ var = *
$ echo "$ var"
*
$ echo $ var
ввод образца
  

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

Bash читать встроенную справку по командам и примеры

Обновлено: 04.05.2019, Computer Hope

В Unix-подобных операционных системах read - встроенная команда оболочки Bash.Он считывает строку текста из стандартного ввода и разбивает ее на слова. Эти слова затем можно использовать в качестве входных данных для других команд.

Описание

read считывает одну строку из стандартного ввода или из файлового дескриптора fd , если используется параметр -u (см. -u ниже).

По умолчанию read считает символ новой строки концом строки, но это можно изменить с помощью параметра -d .

После чтения строка разбивается на слова в соответствии со значением специальной переменной оболочки IFS , внутреннего разделителя полей. По умолчанию значение IFS - «пробел, табуляция или новая строка». Если read встречает читаемые символы до встречи с IFS, он считает эти символы словом. (Для получения дополнительных сведений о IFS см. Разделение слов в bash.)

Наконечник

Чтобы сохранить пробелы в начале или конце строки, обычно указывается IFS = (без значения) непосредственно перед командой read .После завершения чтения IFS возвращается к своему предыдущему значению. Подробнее об этом см. Примеры ниже.

read назначает первое найденное слово name , второе слово name2 и т. Д. Если слов больше, чем имен, все оставшиеся слова присваиваются последнему заданному имени name . Если указано только одно имя , этой переменной присваивается вся строка.

Если имя не указано, ввод сохраняется в переменной с именем REPLY .

Синтаксис

  читать  [ -ers ] [ -a   array ] [ -d   delim ] [ -i   text ] [ -n   nchars ] [ -N   нчар ]
     [ -p   подсказка ] [ -t   тайм-аут ] [ -u   fd ] [ имя  ...] [ имя2  ...] 

Опции

Встроенная команда read принимает следующие параметры:

-a массив Сохраните слова в индексированном массиве с именем array .Нумерация элементов массива начинается с нуля.
-d сечение Установите символ-разделитель на разделитель . Этот символ сигнализирует об окончании строки. Если -d не используется, разделителем строк по умолчанию является новая строка.
Получите строку ввода из интерактивной оболочки. Пользователь вручную вводит символы, пока не будет достигнут разделитель строк.
-i текст При использовании вместе с -e (и только если -s не используется), текст вставляется как начальный текст строки ввода.Пользователь может редактировать текст в строке ввода.
-n nchars Остановить чтение после того, как будет прочитано целое число nchars символов, если не достигнут разделитель строк.
-N nchars Игнорировать разделитель строк. Остановить чтение только после того, как будет прочитано nchars символов, достигнут EOF или истечет время чтения (см. -t ).
-p подсказка Перед началом чтения вывести строку prompt без новой строки.
-r Использовать «исходный ввод». В частности, эта опция заставляет читать буквально интерпретировать обратную косую черту, а не интерпретировать их как escape-символы.
Не повторять нажатия клавиш, когда читает принимает ввод с терминала.
-t тайм-аут Тайм-аут и возврат ошибки, если вся строка ввода не считана в течение тайм-аута секунд. Если значение тайм-аута равно нулю, read не будет читать никаких данных, но возвращает успех, если вход был доступен для чтения. Если тайм-аут не указан, вместо этого используется значение переменной оболочки TMOUT , если она существует. Значение тайм-аута может быть дробным числом, например.г., 3,5 .
-u fd Считывание из файлового дескриптора fd вместо стандартного ввода. Дескриптор файла должен быть небольшим целым числом. Для получения информации об открытии пользовательского файлового дескриптора см. Открытие файловых дескрипторов в bash.

Статус выхода

Статус выхода read равен нулю, если не встречается EOF, превышен тайм-аут, возникает ошибка при присвоении значения name или дескриптор файла, предоставленный для -u , недействителен.

Если тайм-аут превышен, статус выхода больше 128.

Примеры

 при чтении; эхо "$ REPLY"; сделано 

чтение принимает данные с терминала. Введите все, что хотите, и нажмите Enter. Текст отображается на следующей строке. Этот цикл продолжается до тех пор, пока вы не нажмете Ctrl + D (EOF) на новой строке. Поскольку имена переменных не указаны, вся строка текста сохраняется в переменной REPLY .

 при чтении текста; сделать echo "$ text"; сделано 

То же, что и выше, с использованием имени переменной текст .

 при чтении -ep "Введите что-нибудь:" -i "Мой текст" текст; делать
  эхо "$ текст";
сделано 

Предоставляет подсказку и начальный текст для ввода пользователем. Пользователь может стереть «Мой текст» или оставить его как часть ввода. Набрав Ctrl + D в новой строке, цикл завершается.

 echo "Привет, мир!" | (читать; эхо "$ REPLY") 

Заключение команд read и echo в круглые скобки выполняет их в специальной подоболочке. Это позволяет обращаться к переменной REPLY как для read , так и для echo .Дополнительные сведения см. В разделе Среды выполнения команд bash: подоболочки.

 эхо «раз, два, три, четыре» | пока читал слово1 слово2 слово3; делать
  echo "word1: $ word1"
  echo "word2: $ word2"
  echo "word3: $ word3"
сделано 

Вызвать «один, два, три, четыре» и передать его по конвейеру в цикл , а , где читает, читает первое слово в word1 , второе в word2 , а все остальное в word3 . Выход:

 word1: один
word2: два
word3: три четыре 
 эхо «раз, два, три, четыре» | при чтении - массив слов; делать
  эхо $ {wordarray [1]}
сделано 

То же, что и выше, но присваивает слова элементам индексированного массива, wordarray .Нумерация начинается с нуля, поэтому $ {wordarray [1]} возвращает второе слово. Для получения дополнительной информации см. Массивы bash. Выход:

 два 
, а IFS = чтение -r -d $ '\ 0' файл; делать
  эхо "$ файл"
сделано <<(find. -print0) 

Приведенные выше команды представляют собой «правильный» способ использования команд find и read вместе для обработки файлов. Это особенно полезно, когда вы хотите что-то сделать с большим количеством файлов со странными или необычными именами. Давайте посмотрим на отдельные части приведенного выше примера:

, а IFS = 

IFS = (без нуля после знака равенства) устанавливает для внутреннего разделителя поля значение «нет значения».Таким образом, пробелы, табуляции и символы новой строки считаются частью слова, которое сохраняет пробелы в именах файлов.

Обратите внимание, что IFS = следует после , а , гарантируя, что IFS изменяется только внутри цикла и . Например, это не повлияет на find .

 читать -r 

Использование опции -r необходимо для сохранения любых обратных косых черт в именах файлов.

 -d $ '\ 0' 

Параметр -d устанавливает разделитель новой строки.Здесь мы устанавливаем его на символ NULL, нулевой код ASCII. (Экранированный ноль, заключенный в одинарные кавычки, которому предшествует знак доллара, интерпретируется bash как NULL. Для получения дополнительной информации см. Расширение строк с помощью интерпретируемых escape-символов в документации bash.)

Мы используем NULL в качестве разделителя строк, потому что имена файлов Linux могут содержать символы новой строки, поэтому нам нужно их сохранить. (Звучит ужасно, но да, такое бывает.)

Однако NULL никогда не может быть частью имени файла Linux, так что это надежный разделитель.К счастью, find может использовать NULL для ограничения результатов, а не новую строку, если указана опция -print0 :

 <<(найти. -Print0) 

Вот, находят. -print0 создает список всех файлов в и ниже. (рабочий каталог) и разделите все имена файлов NULL. При использовании -print0 все остальные аргументы и параметры должны предшествовать ему, поэтому убедитесь, что это последняя часть команды.

Заключение команды find в <(... ) выполняет подстановку процесса: вывод команды можно читать как файл. В свою очередь, этот вывод перенаправляется на цикл , а цикл с использованием первого « <».

Для каждой итерации цикла while , read считывает одно слово (одно имя файла) и помещает это значение в переменную file , которую мы указали как последний аргумент команды read .

Когда больше нет имен файлов для чтения, read возвращает false, что запускает конец цикла while , и последовательность команд завершается.

while - Выполнить набор действий, пока выполняется определенное условие.
find - поиск файлов в иерархии каталогов.

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *