-1

So im running a script called backup.sh. It creates a backup of a site. Now I have a file called sites.txt that has a list if sites that I need to backup. i dont want to run the script for every site that I need to backup. So what im trying to do is run is like this:

backup.sh $(cat sites.txt)

But it only backups the 1st site thats on the list then stop. any suggestions how i could keep make it go throughout the whole list?

fer
  • 7
  • 2

3 Answers3

3

To iterate over the lines of a file, use a while loop with the read command.

while IFS= read -r file_name; do
    backup.sh "$file_name"
done < sites.txt
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Not sure but I think this could be done without the `IFS=` part? – src Mar 31 '16 at 05:18
  • @src Yeah, with a single argument I guess `IFS` never comes into play – tripleee Mar 31 '16 at 08:05
  • 2
    There is another potential problem, though: If `backup.sh` consumes standard input, it will gobble up the data from `sites.txt` and probably put it somewhere completely in the wrong place. You can prevent that with `backup.sh "$file_name" – tripleee Mar 31 '16 at 08:06
  • Agree, OP did not mention multiple arguments inside `sites.txt` – src Mar 31 '16 at 09:40
  • @tripleee I'd instead redirect `sites` using a different file descriptor, since `backup.sh` presumably has a reason for reading from standard input. `while IFS= read -r file_name <&3; do ...; done <3 sites.txt`. – chepner Mar 31 '16 at 11:53
  • `IFS=` is necessary to preserve leading and trailing whitespace in a line; the fact that `read` has only a single argument prevents word-splitting. – chepner Mar 31 '16 at 11:56
  • Oh right, I missed that detail of `IFS`. The redirection problem is a FAQ e.g. when a backup script uses `ssh` to connect to a remote host; the `ssh` session will usurp standard input even when you didn't mean it to. The fix to redirect `ssh` to read from `/dev/null` is well documented. See e.g. http://stackoverflow.com/questions/9393038/ssh-breaks-out-of-while-loop-in-bash – tripleee Mar 31 '16 at 12:06
  • The interface to any program includes the file descriptors it will read from, so it's really a matter of knowing ahead of time which ones it is safe to use. – chepner Mar 31 '16 at 12:08
1

The proper fix is to refactor backup.sh so that it meets your expectation to accept a list of sites on its command line. If you are not allowed to change it, you can write a simple small wrapper script.

#!/bin/sh
for site in "$@"; do
    backup.sh "$site"
done

Save this as maybe backup_sites, do a chmod +x, and run it with the list of sites. (I would perhaps recommend xargs -a sites.txt over $(cat sites.txt) but both should work if the contents are one token per line.)

tripleee
  • 175,061
  • 34
  • 275
  • 318
0

I think this should do, provided that sites.txt has one site per line (not tested):

xargs -L 1 backup.sh < sites.txt

If you are permitted to modify backup.sh, I would enhance it so that it accepts a list of sites, not a single one. Of course, if sites.txt, is very, very large, the xargs way would still be the better one (but then without the -L switch).

user1934428
  • 19,864
  • 7
  • 42
  • 87