Вопрос или проблема
Я совсем нов по части Linux и выполняю некоторые относительно простые упражнения в bash. Я не могу понять, как взять несколько выводов с использованием подстановочного знака (*) и скопировать их в отдельные строки.
Например, у меня есть 4 файла в домашнем каталоге: file1, file2, File1, File2.
Я хотел попробовать перенаправить f* в новый файл под названием test1, поэтому я написал:
echo f* > $HOME/test1,
когда я выполнил
cat $HOME/test1,
я получил:
file1 file2,
в одной строке. Никто не знает, как разделить строки, не используя nano?
Самое простое решение, но немного хитрое, это ls -d f* >foo
— это зависит от функции(?), что вывод ls
на терминал может отображаться в нескольких колонках, но при перенаправлении (в файл или конвейер) используется только одна колонка.
Следующее простое решение это printf '%s\n' f* >foo
.
Самое старое/традиционное решение это for i in f*; do echo "$i"; done
, но в зависимости от вашей оболочки (или echo
) может возникнуть ошибка для имен файлов, содержащих обратный слеш. Это также может вызвать ошибки для некоторых имен файлов, начинающихся с дефиса, но ваш конкретный подстановочный знак f*
не создаст таких.
Но ни одно из этих решений не удовлетворяет вашему условию использовать (только?) echo
. Это усложняет задачу без видимой причины, но можно сделать это с помощью массива и изменения IFS в подпроцессе:
a=( f* ); (IFS=$'\n'; echo "${a[*]}" >foo)
Обратите внимание, что это работает только в оболочках с массивами, таких как bash (как вы указали), ksh, zsh. Первые три работают в любых POSIX-оболочках (и третий даже в древних пред-POSIX системах).
Ответ или решение
Для того чтобы перенаправить вывод, содержащий имена файлов, соответствующих шаблону f*
, в файл так, чтобы каждое имя файла находилось на отдельной строке, можно использовать несколько методов. Ниже я опишу несколько способов достижения данной цели с использованием команды echo
.
-
Использование
ls
:
Один из самых простых способов — использовать командуls
с параметром-d
, что гарантирует вывод имен файлов в один столбик:ls -d f* > $HOME/test1
Этот метод удобен, но требует использования
ls
, а не толькоecho
. -
Использование
printf
:
Командаprintf
также может быть использована для достижения нужного результата:printf '%s\n' f* > $HOME/test1
Этот способ является хорошей альтернативой, так как он корректно обрабатывает имена файлов, включая те, которые могут содержать пробелы.
-
Цикл
for
сecho
:
Хотя это и не является чисто командойecho
, можно использовать циклfor
для вывода каждого файла на отдельной строке:for i in f*; do echo "$i"; done > $HOME/test1
Этот метод безопасен для имен файлов и хорошо работает в большинстве оболочек. Однако, как вы и заметили, его использование немного выходит за рамки чистого
echo
. -
Использование массивов и изменение IFS:
Если вы хотите использовать толькоecho
, то можно сделать это через массив и изменить переменнуюIFS
:a=( f* ); (IFS=$'\n'; echo "${a[*]}" > $HOME/test1)
Этот метод работает в оболочках, поддерживающих массивы, таких как bash, ksh, zsh. Здесь мы создаем массив
a
, содержащий все элементы, соответствующие шаблонуf*
, затем устанавливаемIFS
(Internal Field Separator) на символ новой строки, что позволяетecho
выводить каждый элемент массива на отдельной строке.
Все предложенные методы позволят вам получить желаемый результат, однако, чтобы использовать именно echo
, лучший выбор — это последний метод с изменением IFS
. Выберите тот вариант, который больше соответствует вашим требованиям и удобен для использования.