Creating an alias that is an incomplete command

0

The documentation from tldp.org doesn't really specify when or how the bash interpreter replaces an aliased string. I'm looking for information on how to create an alias that is an incomplete command.

alias quickscp="scp a.really.long.internal.domain.name:"
quickscp/data/testfile ./testfile

This fails - looks like bash doesn't expand testalias unless it is matching a string with whitespace (^/$ included I assume) surrounding it.

It would be nice if aliases could assume some of the functionality of the C preprocessor, such as macro expansion,

http://tldp.org/LDP/abs/html/aliases.html agrees with me here - "it would be nice if" implies that it does not behave like a C preprocessor. Is there any way to force it? Something specific to the scp case above would solve my problem, but I'd be interested to know if there's a way to get the logic I'm trying to implement as well (for future hackery).

I guess this can be tl;dr'd to: How do I get bash to expand an alias if it isn't surrounded by whitespace?

Brydon Gibson

Posted 2020-01-22T15:06:23.507

Reputation: 527

Answers

4

It's in the definition of a Bash alias that it is a separate word (cf. the manual). I think what you want instead is a shell function:

quickscp () {
  if [[ "$#" -ne 2 ]]; then echo "Need two arguments"; return 1; fi
  scp host.example.com:"$1" "$2"
  return "$?"
}

Call it like:

quickscp source target

As a bonus, you can do parameter checking and you'll get the return code of the scp command, so you can do quickscp foo bar && echo "yay" or similar chaining of commands.

slhck

Posted 2020-01-22T15:06:23.507

Reputation: 182 472

2

I don't think you can do this with an alias. How about a function?

unalias quickscp
quickscp () (
   first="$1"
   shift
   exec scp "a.really.long.internal.domain.name:$first" "$@"
)

Notes:

  • unalias because the portable definition of a function can collide with already defined alias.
  • The function body is deliberately placed in a subshell to make the variable named first local, without a non-portable local first statement.
  • exec because we no longer need the subshell after scp starts.

A completely different approach is to define a host in your SSH config (global: /etc/ssh/ssh_config; user-specific: ~/.ssh/config):

Host foo
Hostname a.really.long.internal.domain.name

Then proceed like this:

scp foo:/data/testfile ./testfile

This will work with ssh or scp. It has nothing to do with aliases in a shell.

Kamil Maciorowski

Posted 2020-01-22T15:06:23.507

Reputation: 38 429

There is no point in $@, since there is only one target argument in scp. – slhck – 2020-01-22T15:34:38.723

@slhck I know. I wanted the approach to mimic a desired alias-like behavior for any command. Some other commands may make sense with $@. – Kamil Maciorowski – 2020-01-22T15:37:12.867

Sure, I was going to do the same, but figured it wouldn't make a lot of sense, particularly when the options for scp (should the user want any) would have to be placed before the source/target. Good alternative with the hostname definition! – slhck – 2020-01-22T16:04:55.480

1

One trick I know of is using en empty string as a delimiter for expansion:

quickscp""/data/testfile ./testfile

harrymc

Posted 2020-01-22T15:06:23.507

Reputation: 306 093

This doesn't seem to work for me. I prefer this to the other answer just because it's quicker to write aliases that go to various depths, and it feels more temporary (my intent). Is this shell specific? I'm using GNU bash 4.3.48 – Brydon Gibson – 2020-01-22T15:28:48.000

I'm tried it in bash using Ubuntu on Windows and it worked for me. Seems like some bash difference. – harrymc – 2020-01-22T15:31:38.603