I want to make small bash scripts that will automate some stuff for me in new machines.

The only thing I still do manual is creating files with vi and pasting the text on the file.

How can I generate file X with "text i need here" inside it on bash? Without having to press enter, overwrite files if necessary and also create directories as needed?


Example : Replacing a default sshd_config file with my version and creating a file with my public SSH key inside it. Generating another .sh file on-the-fly. Stuff like that.

  • 1
    Use Ansible or similar software to automate configuration and deployment on new and existing machines. I'm not sure what are you trying to do. Provide some examples please – mrc02_kr Aug 29 '17 at 7:54
  • echo "text i need here" > some/file? – muru Aug 29 '17 at 7:55
  • If it's the redirecting to file part, see How do I redirect command output to a file? – muru Aug 29 '17 at 8:07
  • @muru well I do think that is a duplicate now :/ but I also feel my question will be easier found by people looking for something like this, and the answer is more noob friendly. Well whatever, thanks for the help tho – Freedo Aug 29 '17 at 9:16

For text content, the easiest, especially if the text contains multiple lines is to use a here-document. Add these lines to your script for instance for your script to create a file.txt with this text:

cat << 'EOF' > file.txt
Here is some text
or other

(you can use anything in place of EOF above as the end of file marker provided it doesn't occur in the text to insert. The first EOF has to be quoted to prevent any expansion inside the here-document).

For files with arbitrary content, you can use uudecode. It also lets you specify the permissions for the file being created. For instance for a script to create a foo file with the content and permissions of /bin/ls, do:

(echo 'uudecode << "_EOF_"'
uuencode -m /bin/ls foo
echo _EOF_) >> your-script

Which will add the correspond code to your script. Something like:

uudecode << "_EOF_"
begin-base64 755 foo

With the content of /bin/ls encoded in base64.

That assumes the uudecode is available on the machine you're going to run that command in. But that should generally be the case as uudecode is a POSIX command.

You can extend that to create several files by encoding a compressed tar archive:

(echo 'uudecode << "_EOF_" | gunzip | tar xpf -'
tar cf - file1 file2 file3 dir/file4 | uuencode -m -
echo '_EOF_') >> your-script

(assuming the target system has gunzip and tar (not POSIX commands but quite common)).

That also has the benefit of letting you encode additional file metadata like ownership or access and modification time (and more like ACLs and extended attributes, and hard link relationship with some tar implementations). It also allows you to easily create non-regular files like directories, symlinks, devices...

See also the shar utility which can help you create portable self-extractable archives.

  • will this require a enter after pressing the button like the other answer? – Freedo Aug 29 '17 at 8:17
  • @Freedo, I don't understand what you mean. This is about creating a script that creates some files with some content, I don't see where a key or button would come into the picture. – Stéphane Chazelas Aug 29 '17 at 8:46
  • if I execute your echo command in the terminal just to test, it works, but it requires me to press enter after it to get me back to the terminal, will this behavior happen when executing the script? Also is there a way to make echo overwrite files and create directories as necessary? a example here imgur.com/a/H0LFg – Freedo Aug 29 '17 at 9:19
  • @Freedo, echo outputs text; >, <> and >> redirections, tar, uudecode create files (> truncates them and opens at the start if they existed, >> opens at the end and doesn't truncate, <> opens at the beginning without truncating); tar, mkdir can create directories. – Stéphane Chazelas Aug 29 '17 at 9:29
  • I know about mkdir, I was asking more about making echo/cat create the directory if necessary so I don't need to create it before running it. in the screenshot I provided I had to press enter to go back to terminal, but it worked. – Freedo Aug 29 '17 at 9:38

A script could do

sudo mv /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
sudo cp "$HOME/my_configs/sshd_config" /etc/ssh/
sudo chmod go-w /etc/ssh/sshd_config


sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
cat "$HOME/my_configs/sshd_config" | sudo tee /etc/ssh/sshd_config >/dev/null

to back up any old sshd_config and then install a new one.

I mean, it's just a matter of having a collection of files somewhere and then copy them to the correct locations and making sure that the installed files have the correct permissions. This could be automated with a script.

There are however specialized software for doing automatic provisioning and configuration management, such as Ansible and Puppet.

These types of software may become more interesting as soon as you need to set up more than a couple of machines. We, for example, use Ansible to set up private Docker containers for our customers on our compute-cluster.

  • I don't want to transfer files to the machine before doing anything, it's way better to generate the files on-the-fly there. And those softwares are probably way beyond my needs. But thanks for the answer :D – Freedo Aug 29 '17 at 9:11
  • @Freedo There's nothing stopping you from transferring a script and some files from somewhere to the machine and running the script there using scp and ssh. – Kusalananda Aug 29 '17 at 9:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.