0

Starting from this answer, I want to archive anything using "archive name_dest [folder+filter]"

I've tried:

archive() { tar cjf "`(date '+%Y.%m.%d-%Hh%Mm%Ss')`-$1.tar.bz2" "$2"; }

When I do this special chars are not handled:

> archive dev "dev/*"
tar: dev/*: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

(of course the dev is a directory in my current path) What is the proper way? I would really like to type only archive dev dev/*.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
Olivier Pons
  • 15,363
  • 26
  • 117
  • 213
  • `archive dev dev` should achieve what you want. The error is because you quoted second argument, and `dev` directory does not contain a file name `*`. – Philippe Mar 29 '20 at 19:03
  • If I dont quote the second argument I get another type of error. If you could try you would see what I mean – Olivier Pons Mar 29 '20 at 19:07
  • The second parameter has be a directory, not a list of files you'd get with `dev/*`. Run `archive dev dev` (or if you meant `/dev` then `archive dev /dev`) – Arkadiusz Drabczyk Mar 29 '20 at 19:57

1 Answers1

4

Wildcards (like *) only expand into a list of matching filenames when they're not in quotes. One possibility would be to leave $2 unquoted in the function:

archive() { tar cjf "`(date '+%Y.%m.%d-%Hh%Mm%Ss')`-$1.tar.bz2" $2; }

...but that can have some unpleasant consequences. Most obviously, if you're trying to archive a folder with spaces or some other shell metacharacters in the name, it'll get confused because those aren't in quotes either.

A much better solution is to pass the folder+pattern unquoted in the first place, so it expands before the function gets invoked. You run

archive dev dev/*

...and the shell expands it to something like

archive dev dev/file1 dev/file2 dev/file3

But then you have to write the function so it doesn't just archive $2, but all arguments starting at $2. This isn't too hard; just record $1, use shift to remove it from the arg list, then use "$@" to get all remaining arguments. And as long as we're using local variables, I'd put the destination filename in one as well (just for general neatness):

archive() {
    local name_dest="$1"
    local archive_name="$(date '+%Y.%m.%d-%Hh%Mm%Ss')-${name_dest}.tar.bz2"
    shift
    tar cjf "${archive_name}" "$@"
}
Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151