1

I want to copy a file whose name contains timestamp like -

image-abc-20201113-1703.bin

at the location /my/path/for/the/image.

And I want to copy this image to a device - mydevice which is saved under ~/.ssh/config

Since the name of the file is not constant, i cant hardcode it in the script.

So i use regex to copy that file like -

scp /my/path/for/the/image/image-abc-*.bin mydevice:flash:<file_name>

So I need to mention the name of the source file that is getting copied in the place of file_name

How can I achieve this?

Darshan L
  • 279
  • what is this syntax? mydevice:flash: . scp will work fine if the destination is an existing directory, you don't need to give the filename if you want to keep the old one. Btw, this is not regex but globbing. – pLumo Nov 13 '20 at 11:46
  • flash is the file system I guess, without which copy doesn't work. Even i expected it to work without mentioning the file name in the destination. But not sure, unless I mention the destination file name scp doesn't work – Darshan L Nov 13 '20 at 11:48

1 Answers1

2

If you feel that you have to give the correct destination filename, which I don't think you should need to do, then use your filename globbing pattern (which is not a regular expression) in a loop:

for pathname in /my/path/for/the/image/image-abc-*.bin
do
    [ -e "$pathname" ] &&
    scp "$pathname" "mydevice:flash:$(basename "$pathname")"
done

This would copy all files whose names matches the given globbing pattern. The -e test makes sure that the pathname in $pathname actually exists before calling scp (the pattern would remain unexpanded if there was no matching names found).

The basename utility is used here to extract the filename portion of the pathname. This is then used as the destination filename. One could also use the parameter substitution "${pathname##*/}" in place of the command substitution calling basename.

If you're certain that your pattern would only match a single file, you could also do

set -- /my/path/for/the/image/image-abc-*.bin
[ -e "$1" ] && scp "$1" "mydevice:flash:$(basename "$1")"

This is essentially the same thing as only running the first iteration of the above loop, using the positional parameters to hold the expanded list of pathnames matching the pattern.

terdon
  • 242,166
Kusalananda
  • 333,661
  • As I'm sure there is only one file with that name and don't need looping, can I simplify this? – Darshan L Nov 13 '20 at 12:12
  • @DarshanL See the second bit of code. This could be placed on one single line if you separate the set from the [ -e ... ] && ... bit with ; (in other words: replace the newline with ;). – Kusalananda Nov 13 '20 at 12:13
  • Can you help me understand what does set -- means? – Darshan L Nov 13 '20 at 14:38
  • Should I have to keep the second argument to scp within double quotes? Not needed right? – Darshan L Nov 13 '20 at 14:42
  • @DarshanL The -- signals the end of options to the set command. See https://unix.stackexchange.com/questions/11376. You should quote every expansion to avoid word splitting and filename globbing. See https://unix.stackexchange.com/questions/131766 and https://unix.stackexchange.com/questions/68694 – Kusalananda Nov 13 '20 at 16:43