0

I have to copy a file Test_*.txt to Test_20190101_Timestamp.txt, where * is a wild card and 20190101 is the date.

cp test_*.txt test_*_"$(date +%Y%m%d-%H%M%S)".txt

When I copy the files the output copy is also coming as Test_*_Timestamp.txt. How can I copy the entire file without the wildcards?

I've also tried this, but it also failed

cp test_*.txt test*_"$(date +%Y%m%d-%H%M%S)".txt 
cp: target 'test*_20200102-160523.txt' is not a directory
roaima
  • 107,089
  • 14
  • 139
  • 261
  • do you mean it is a list of files or a unique file with "*" char in its name ? – francois P Jan 02 '20 at 19:39
  • Does this answer your question? [Why does my shell script choke on whitespace or other special characters?](https://unix.stackexchange.com/questions/131766/why-does-my-shell-script-choke-on-whitespace-or-other-special-characters) – jesse_b Jan 02 '20 at 19:57
  • 3
    Can you give us the exact command you're using to copy the file? – doneal24 Jan 02 '20 at 19:58
  • cp test_*.txt test_*_"$(date +%Y%m%d-%H%M%S)".txt – Aditya Kutcharlapati Jan 02 '20 at 20:52
  • Francois: I have one file, but i have to automate it through ETL tool for which i have to use cp command in the tool. When i copy the file with the wildcard, the wild card the output is also coming with * but not the actual file name – Aditya Kutcharlapati Jan 02 '20 at 20:54
  • cp test_*.txt test_*_"$(date +%Y%m%d-%H%M%S)".txt cp: target ‘test_*_20200102-160523.txt’ is not a directory – Aditya Kutcharlapati Jan 02 '20 at 21:06
  • I've copied your comments back into the question, so they can be more easily seen by people wanting to help. Please double-check that I've interpreted your commands correctly, as it is essential the text is correct. (If it's not, please [edit] it.) – roaima Jan 02 '20 at 22:34

2 Answers2

1

You need to loop over the files:

for file in Test_*.txt; do
    fileroot=${file%.txt}    # remove the extension
    cp -v "$file" "${fileroot}_Timestamp.txt"
done
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
0

The problem - as you may have found out - is that you assumed in your original attempt that the actual value of the wildcard is "transferred" between the different arguments of your command (i.e. from your source filename to your intended target filename).

However, this is not how wildcard expansion (or, rather, "glob expansion") works in the shell. Rather, everywhere a wildcard appears, the shell expands this internally to a list of matching files and executes your command as if you had specified the entire list (see e.g. this tutorial on shell globbing). So, if you have files

Test_a.txt
Test_b.txt
Test_c.txt

in your directory, your cp command would actually behave as if you had typed

cp Test_a.txt Test_b.txt Test_c.txt Test_*_20200102-160523.txt

Since the last argument is taken as the destination of the copy command, and you have specified multiple source files, cp assumes this to be a directory and complains that no directory of that name exists.

Why now does it complain about there being no Test_*_20200102-160523.txt directory with a literal * in it? The standard behaviour (at least of the bash) is that if you specify a wildcard character and there is no matching file present, the wildcard character will be interpreted literally as itself - and since your expression Test_*_20200102-160523.txt was intended as target filename, it does not yet exist in the current directory.

This is the reason behind @glennjackman's answer that you need to loop over your input files to achieve the desired result.

AdminBee
  • 21,637
  • 21
  • 47
  • 71