Оболочка - записывает содержимое переменной в файл

98

Я хотел бы скопировать содержимое переменной (здесь называется var) в файл.

Имя файла хранится в другой переменной destfile.

У меня проблемы с этим. Вот что я пробовал:

cp $var $destfile

Я также пробовал то же самое с командой dd ... Очевидно, оболочка подумала, что $varэто относится к каталогу, и поэтому сказала мне, что каталог не может быть найден.

Как мне обойти это?

user1546083
источник
2
Уточните свой вопрос, разместив правильно отформатированный код, который показывает, как вы заполняете свои переменные, и все соответствующие сообщения об ошибках в точности так, как они появляются.
Тодд А. Джейкобс
2
Что вы имеете в виду под «копированием содержимого переменной» в каталог? Указывает ли $varимя файла или какой-то текст, который должен быть записан в файл? Если в нем указан текст, то каково имя файла, в который вы хотите записать этот контент?
jahroy
$ var содержит текст, который я хочу скопировать, а файл, в который он должен быть записан, определяется пользователем, поэтому я в первую очередь использую переменную.
user1546083
1
Возможно, $destdirследует назвать $destfileего, чтобы оно не вводило в заблуждение ... Название $destdirпредполагает, что оно указывает каталог, а не файл. Это сделало бы весь ваш вопрос простым и легким для понимания.
jahroy

Ответы:

149

Используйте echoкоманду:

var="text to append";
destdir=/some/directory/path/filename

if [ -f "$destdir" ]
then 
    echo "$var" > "$destdir"
fi

В ifтестах , которые $destdirпредставляют файл.

>Добавляет текст после усечения файла. Если вы хотите только добавить текст в $varсуществующее содержимое файла, используйте >>вместо этого:

echo "$var" >> "$destdir"

Команда cpиспользуется для копирования файлов (в файлы), а не для записи текста в файл.

pb2q
источник
4
Требуется больше кавычек - прямо сейчас любые пробелы в значении переменной будут преобразованы в один пробел, глобальные выражения будут расширены и т. Д.
Чарльз Даффи
2
Еще одна вещь - вам нужно пространство между закрывающей кавычки и ]ин "$destdir"].
Charles Duffy
3
echoтакже добавляет завершающую новую строку к вашей переменной.
Бен Дилтс,
6
Это терпит неудачу , если $varесть -e text to append, а на самом деле does't написать-e
Eric
1
Поскольку echo $varон полагается на оболочку для расширения вашей переменной, он не очень хорошо работает с такими вещами, как пробелы и специальные символы. Вы можете использовать perl -e 'print($ENV{var})'вместо этого, и он будет выводить точное значение переменной.
Блейк Митчелл
41

echoимеет проблему, что если он varсодержит что-то подобное -e, он будет интерпретирован как флаг. Другой вариант printf, но printf "$var" > "$destdir"он расширит любые экранированные символы в переменной, поэтому, если переменная содержит обратную косую черту, содержимое файла не будет совпадать. Однако, поскольку printfобратная косая черта интерпретируется только как экранирование в строке формата, вы можете использовать %sспецификатор формата для сохранения точного содержимого переменной в файле назначения:

printf "%s" "$var" > "$destdir"

Trebawa
источник
1
printf также хорош, если у вас есть новые строки в строке переменной, например, из тройной кавычки или heredoc. echo плохо обрабатывает новые строки.
beeflobill
@beeflobill, можете ли вы объяснить, как «echo плохо обрабатывает символы новой строки». Единственное, что я видел, это то, что echo добавляет новую строку. Что действительно echo "$var" > destfileнеправильно.
SensorSmith
@SensorSmith В своих экспериментах я вижу, что когда в строке есть «\ n», эхо выводит символ новой строки. Но, если строка имеет фактический символ новой строки, echo не будет печатать его. Не знаю почему.
beeflobill
1
В основном проблема переносимости (и надежности). unix.stackexchange.com/a/65819… или для смертоносных из нас: printfлучше, продолжайте.
user3342816
30

Ни один из приведенных выше ответов не работает, если ваша переменная:

  • начинается с -e
  • начинается с -n
  • начинается с -E
  • содержит, \за которым следуетn
  • не должно добавляться лишняя новая строка после него

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

В bash вы можете использовать «здесь строки» как:

cat <<< "$var" > "$destdir"

Как отмечено в комментарии ниже, использование ответа @ Trebawa (сформулированного в той же комнате, что и моя!) printf- лучший подход.

Эрик
источник
5
Насколько я могу судить, cat всегда будет вставлять новую строку в конец файла, независимо от того, нет ли новой строки в конце переменной (хотя, возможно, в большинстве случаев это хорошо). С помощью Printf ответа , кажется , чтобы избежать вставок завершающего символа новой строки.
Ash
@Ash еще одно преимущество printfover catзаключается в том, что первая - это встроенная оболочка, которая всегда будет выполняться быстрее, чем внешний двоичный файл.
Геза Торок,
7

Если я вас правильно понял, вы хотите скопировать $varв файл (если это строка).

echo $var > $destdir
qwertz
источник
Вот как это делается. Использование этой cpкоманды заставит оболочку интерпретировать первый аргумент как имя файла или каталога.
jahroy
5
Если вы не заключаете $varв кавычки, в некоторых случаях содержимое файла не на 100% совпадает с содержимым $ var. Например, при "повторении" переменных, содержащих ключи RSA, вы получите недопустимый ключ в файле.
srigi
6
Сбой, если $varсодержит пробелы или-e
Эрик
1

Когда вы говорите «копировать содержимое переменной», эта переменная содержит имя файла или имя файла?

Я предполагаю, что ваш вопрос $varсодержит содержимое, которое вы хотите скопировать в файл:

$ echo "$var" > "$destdir"

Это отобразит значение $ var в файл с именем $ destdir. Обратите внимание на цитаты. Очень важно заключить "$ var" в кавычки. Также для "$ destdir", если в имени есть пробел. Чтобы добавить это:

$ echo "$var" >> "$destdir"
Дэвид В.
источник
3
Не работает, если varсодержит-e
Эрик
1
Передача двойного дефиса в качестве первого аргумента для echo завершения списка опций, таким образом, решает проблему, поднятую @Eric:echo -- "$var" >> "$destfile"
Géza Török
1

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

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

Использовать это:

printenv var >file

Это означает, что в случае вопроса OP:

printenv var >"$destfile"
Кристиан Худжер
источник