Saturday, August 11, 2012

Rocking Bash with ... PHP?!?

Here's another solution to the common scripting problem of adapting ls output for use by other commands ... solved with a (very) little PHP!

So I'm using tar to create a simple backup for a web site. Only now the website has podcasts, and I don't need to back those up. I've got a copy elsewhere, and they dwarf the size of the original site.

tar lets me specify a whole set of files and folders, so that's not the problem. I just want an automated way to specify "everything, but not this and not that." I can use ls to get a list of files, but how do I remove just a few programmatically, and how do I get ls to return the full path?

To get the list of all files in my public_html folder, one per line:

ls -a1 $HOME/public_html

To get the path to my public_html folder:

ls -d $HOME/public_html

Now, if I pipe the file names to a PHP script, and pass in the parent folder as an argument, I can use PHP to generate the full path and also selectively cull out items I don't want (including '.' and '..', which ls includes unconditionally). The -R flag runs the PHP script once for each line in the input. Very convenient.

ls -a1 $HOME/public_html | \
  php -R \
    'if(!in_array($argn, array(".","..","podcasts"))) echo $argv[1]."/".$argn."\n";' \
    $(ls -d $HOME/public_html)
$argv[] contains the command-line arguments. $argn is the line from stdin.

The completed command looks like this. It seems like there ought to be a simpler way, but this works, and I will still be able to read this next time I need to modify the script. Neat.

tar -czf $HOME/backups/web-$(date +%Y-%m-%d).tar.gz \
  $(ls -a1 $HOME/public_html | \
    php -R \
      'if(!in_array($argn, array(".","..","podcasts"))) echo $argv[1]."/".$argn."\n";' \
      $(ls -d $HOME/public_html))

No comments:

Post a Comment