1

I am trying to create a bash alias to do the following:

  1. create a folder (with the current date as the folder name)
  2. move (or copy, either is fine with me) a file from the current folder into the new folder.

The filename is passed to the alias as a variable. E.g., my-alias file.txt

Here are a few of the ways I've tried to go about it (although I've tried quite a few more variations):

alias my-alias="mkdir -v -p '$(date +%F)-List' && cp $1 './$(date +%F)-List/$1' && cd '$(date +%F)-List'"

alias my-alias="mkdir -v -p '$(date +%F)-List' && cp $1 ./$(date +%F)-List/$1 && cd '$(date +%F)-List'"

alias my-alias="mkdir -v -p '$(date +%F)-List' && cd '$(date +%F)-List' && cp ../$1 ./$1"

I've tried many ways of writing the command, and none work.

What am I over looking?

This is on Mac OS which should be the same as most other Linux environments.

UPDATE: WHERE I WENT WRONG

I've realised where I was getting confused. I have a lot of aliases set up that "appear" to receive arguments. I set them up a long time ago (some years ago). I now realise that the aliases only seem to receive the arguments because an alias can process whatever follows it when entered on command line. But it will only process those "arguments" if they are at the end of the command string the alias refers to, and in the same order. So once I started trying to shuffle the arguments around in my aliases command string, the alias would break. So yes, the best approach is to use a function.

2
  • 1
  • @steeldriver Thanks. So are you suggesting I use a function instead of an alias? (as detailed in the accepted answer on that question). Or are you suggesting one of the other alias based answers on that question is applicable?
    – inspirednz
    Jun 28, 2020 at 2:37

4 Answers 4

4

If you must use alias, here's one that works by using -t to specify the destination directory before the actual argument for the file being moved:

alias my-alias="mkdir \$(date +%F); mv -t \$(date +%F)"

Works on Linux, I don't have a MacOS machine to test with though.

6
  • @HaukeLaging I did test the code (on Linux), I suppose I should have put that in the answer though.
    – archfan
    Jun 28, 2020 at 3:23
  • If I run alias testalias='echo \$(date +%F)' I get bash: syntax error near unexpected token (' and that makes sense. My shell is GNU bash, Version 5.0.11. Jun 28, 2020 at 3:38
  • @HaukeLaging The single quotes mean the \$ isn't interpreted as escaping the $, but instead as wanting to execute echo \$(date +%F). I used double quotes in my answer, so the back slash escapes the $. alias testalias="echo $(date +%F)" and alias testalias='echo $(date +%F)' both will run without issues.
    – archfan
    Jun 28, 2020 at 3:44
  • Right, I didn't read that carefully enough. Apologies. Jun 28, 2020 at 3:55
  • I am marking Gordon Davidson's answer as the correct answer, because although your (@archfan) answer might work (I haven't actually tested it, but I assume it does), using a function is the better way to achieve what I needed to do. Thanks very much for your solution though. Much appreciated.
    – inspirednz
    Jun 29, 2020 at 23:26
3

Use a function instead of an alias. This is pretty much always the answer if you run into trouble getting an alias to work. Especially if you're trying to use arguments (e.g. $1), since aliases don't really take arguments.

Also, you should pretty much always put double-quotes around parameter and variable references (i.e. "$1" instead of just $1). And don't run date multiple times, since it's possible (if improbable) you'll get different results; run it once and store the result in a variable. Try this:

my-function() {
    local subdir="$(date +%F)-List"
    mkdir -v -p "$subdir" &&
        cp "$1" "$subdir/$1" &&
        cd "$subdir"
}
2
  • Even if there was no risk of getting different results one should never run unnecessary processes. Here it does not really matter but in other cases that can seriously degrade performance. Jun 28, 2020 at 3:26
  • Marking this as the correct answer because although archfan's answer might work (haven't actually tested it, but I assume it does), using a function is the better way to achieve what I needed to do.
    – inspirednz
    Jun 29, 2020 at 23:25
1

As the answers to the other questions indicate: Aliases are just not good at handling parameters. You can even see that:

param=foo; do something with "$param"

That is how parameters work: First (both in time and in the command line) you set them, then you use them. In contrast to that:

<alias string with several commands to be expanded> <parameter>

The parameter can be a parameter to the last command in the alias. That is not what you need.

You can do this with an alias by building it as a single command from the shell's perspective but it is questionable whether that is a useful approach:

alias testalias='bash -c "echo \$1; echo \$1-" bash'
$ testalias foo
foo
foo-

One argument against it is that the quoting is complicated. Even I got that wrong first.

-1

You need to create a function. mkdir -v -p '$(date +%F)-List' will only get evaluated at the time the alias was created

2
  • You should provide the complete code so that it is clear what you mean. Jun 28, 2020 at 3:56
  • Thanks for the suggestion. Your answer is too brief to make much sense to me or to be useful. I suggest you consider spelling it out a bit more than you have. Cheers...
    – inspirednz
    Jun 29, 2020 at 23:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .