tcsh-org / tcsh

This is a read-only mirror of the tcsh code repository.
https://www.tcsh.org/
Other
232 stars 42 forks source link

Unable to escape @ char in filename in alias #51

Closed renfrow closed 1 year ago

renfrow commented 1 year ago

alias cpr 'cp /where/ever/@template.txt $1'

TCSH-Prompt> cpr newfile.txt
cp: missing destination file operand after '/where/ever/@template.txt'
Try 'cp --help' for more information.

Ditto for '.../\@template.txt...' Ditto for '.../\'@\'template.txt...' Ditto for '.../\'@\'template.txt...' Ditto for '.../'''@'''template.txt...' Ditto for '.../\\@template.txt...'

alzwded commented 1 year ago

Hey @renfrow , I think it's because $1 should rather be \!:1. $1 means $argv[1], \! substitutes for the current invocation of the alias, so \!:1 is the first parameter to the alias itself.

/tmp> echo 'hi' > a@b.c
/tmp> alias cpr 'cp /tmp/a@b.c \!:1'
/tmp> cpr 2
/tmp> cat 2
hi

Also, I'd alias that as 'cp -T /whatever/@template.txt !:*' to allow myself more arguments to cp, but that's just me.

Side note, I have tcsh 6.24.01 compiled from source.

/tmp> echo $version
tcsh 6.24.01 (Astron) 2022-05-12 (x86_64-unknown-linux) options wide,nls,dl,al,kan,sm,rh,color,filec
suominen commented 1 year ago

Or you could just not use an argument selector at all:

> alias cpr 'cp /tmp/a@b.c'
> echo hi > /tmp/a@b.c
> cpr 2
> cat 2
hi

Using an argument selector would let you ignore additional arguments, though, if that really was your goal:

> alias cpr 'cp /tmp/a@b.c \!^'
> cpr 3 4
> cat 3
hi
> cat 4
cat: 4: No such file or directory
suominen commented 1 year ago

Additionally, I'm unable to reproduce the error reported by @renfrow both directly on the command line and by using source to get $1 to expand to something.

> alias cpr 'cp /tmp/a@b.c $1'
> echo hi > /tmp/a@b.c
> cpr 1
> cat 1
hi
> echo cpr 7 > oo
> source oo 12
cp: target '7' is not a directory
renfrow commented 1 year ago

I perhaps was not clear: the name of the file is '@template.txt' (without the single quotes). That is to say, the first character of the filename is the at sign '@' (without the single quotes)(octal 100, decimal 64, hex 40). I am not attempting to use the (t)csh builtin command @.

What I would expect from this alias is that 'cpr newfile.txt' would be a copy of '@template.txt' named 'newfile.txt'. I copied this alias from another alias where the template file does not begin with '@' (octal 100, decimal 64, hex 40).

I work on both windows desktop, and linux via putty. On windows the '@' char sorts to the top of the folder. I sftp'd the template to the remote VPS linux box without considering that the '@' would throw a monkey wrench in the remotely copied alias (I very rarely use Powershell/cmd on windows). Until this error occured, I was not aware that '@' was a command. And had I known I would not have renamed the file as single quotes protected the '$' from being special, and I would have thought it would also protect the '@'. I hope I've made some sense :).

NOTE: you can type 'cp @template.txt newfile.txt' at a tcsh prompt and not get an error, it's in the alias(ing) that the problem occurs. NOTE2: version tcsh 6.21.00 (Astron) 2019-05-08 (x86_64-unknown-linux) options wide,nls,dl,al,kan,sm,rh,nd,color,filec

alzwded commented 1 year ago

Okay, I now get what you're saying. I can't reproduce it on 6.24.01 on Ubuntu even with a bare @ as filename.

/tmp> echo 1 > @
/tmp> rm -f 2
/tmp> alias cpr 'cp @'
/tmp> cpr 2
/tmp> cat 2
1

I tried to build the 6.21 tag to see if it reproduces there, but I got a strange compile/link error and gave up.

alzwded commented 1 year ago

Okay, I got 6.21 compiled and running, and I cannot reproduce.

tcsh-6.21> ./tcsh
tcsh-6.21> cd /tmp
/tmp> echo hi > @template
/tmp> alias cpr 'cp @template \!:1'
/tmp> cpr 2
/tmp> cat 2
hi
/tmp> echo $version
tcsh 6.21.00 (Astron) 2019-05-08 (x86_64-unknown-linux) options wide,nls,dl,al,kan,sm,rh,color,filec

(okay, let's try to do it like the pr...)

/tmp> alias cpr 'cp /tmp/@template $1'
/tmp> cpr 3
/tmp> cat 3
hi
/tmp> echo $version
tcsh 6.21.00 (Astron) 2019-05-08 (x86_64-unknown-linux) options wide,nls,dl,al,kan,sm,rh,color,filec

To my (somewhat limited knowledge) @ is only meaningful (i.e. it does the whole expression math thing) if it's the first token on a line, but your line starts with cpr or cp or whatever.

It seems we have the same config options enabled.

Maybe it's a Cygwin thing, but I don't have a Windows machine available right now to test.

I've tried with `\x{40}' but that doesn't seem to get interpreted during an alias.

Can you try with set echo, maybe it gives more clues?

Or, call it quits and create /usr/local/bin/cpr with the cp command. I can't seem to reproduce it on either 6.21 or 6.24.

renfrow commented 1 year ago

I haven't been using cygwin, just drag-n-drop on windows.

OK, just redid the alias, from scratch, but, with an important change. The FULL alias was: alias cpr 'cp /where/ever/@template.txt $1 && chmod +w $1'

When I posted it, I removed the '&& chmod +w $1', thinking that was superfluous. It wasn't. I redid the alias without that part, and it worked, as everyone else's did. I tried replacing the '&&' with a ';', still got the error.

(I eventually did a bash script just so I could motor on, until I saw that you'd continued looking at this, and revisited it this morning.)

alzwded commented 1 year ago

@renfrow the takeaway is that tcsh's aliases use \!:1 (or 2 or * or $ or whatever), not the dollar-sign syntax. Your alias should work if you use the escaped exclamation point instead. $argv is something you pass to a script/executable, aliases get substituded while the line is being read and they don't get argv.

Your alias caused cp to error out because $1 was empty. Use set echo to see what's actually executing.

suominen commented 1 year ago

@renfrow The other takeaway is that if you are reporting a bug or error, or just asking a question, please report exactly what you did, or if you don't want to report that, at least verify that what you are reporting is actually accurate.

This saves a lot of time for everybody.

Thanks.