You seem to want to copy a particular file from ~/Downloads
to ~/Documents/books
.
The first thing to note is that ~
does not behave as a variable. In particular, it does not expand to the path of your home directory when it's quoted. In scripts, it's therefore better to use $HOME
to refer to the home directory.
The second thing is that you seem to add literal single quotes to the value of your variable $a
. This is not necessary, and will only result in a "No such file or directory" error (because the file does not have single quotes in the filename).
The third thing is that you should try to avoid using ls
in scripts. In this case, for example, if $1
is simply the name of a file in ~/Downloads
you don't have to search for it at all. Also, using grep $1
is problematic for a variety of reasons:
grep
is primarily used on text documents. Filenames may theoretically contain newlines, which makes "grepping" filenames only work if one knows that the names or "nice".
$1
is unquoted an may therefore confuse grep
if it contains spaces or other special characters. If $1
is *
, it would expand to all filenames in the current directory, for example.
- If the string
$1
starts with a dash, it will be taken as an option to grep
.
So, your script may be written as
#!/bin/sh
name="$HOME/Downloads/$1"
printf 'The filename is "%s"\n' "$name"
cp "$name" "$HOME/Documents/books"
The printf
command here is to output the name of the file that we picked. I'm outputting double quotes around the name, but the name does not have double quotes in it. Instead, I'm making sure to quote $name
in the call to cp
on the last line. In fact, I'm making sure to quote all expansions that I know would otherwise result in the shell splitting up the variable's value.
You would use that script as
./script.sh 'Ian Goodfellow, Yoshua Bengio, Aaron Courville - Deep Learning [pre-pub version] (2016, MIT Press).pdf'
The name of the file has to be quoted since it contains spaces and characters that are otherwise special in the shell.
If you want your script to look for a file that contains a word given on the command line, so that you could say
./script.sh Goodfellow
Then use the given string in a globbing pattern:
#!/bin/sh
for name in "$HOME/Downloads"/*"$1"*.pdf; do
printf 'Will copy the file "%s"\n' "$name"
cp "$name" "$HOME/Documents/books"
done
Now the script will take the first argument and loop over all .pdf
files in ~/Downloads
that contain the given string in the filename. Each such file will be copied to ~/Documents/books
.
If you're on a Unix where cp -v
will verbosely copy files, the script may be shrunk down further:
#!/bin/sh
cp -v "$HOME/Downloads"/*"$1"*.pdf "$HOME/Documents/books"
This prevents you from formatting the output yourself ("Will copy ...") as we're no longer looping over the filenames matching the given pattern. Instead we just rely on the fact that if you give multiple filenames to cp
(and the globbing pattern may well expand to multiple filenames), then these can be copied with a single command to some destination directory.
See also:
$1
originally? – Kusalananda Apr 15 '20 at 15:31