I am trying to copy all files in a directory starting with a certain prefix using wildcard. Here is my script
#!/bin/bash
path="/home/scoubidou/recovered/"
prefix="f"
for i in "$#"
do
if [ ! -d "$path$prefix$i" ]; then
mkdir $path$prefix$i
fi
echo $path$prefix$i* $path$prefix$i
mv $path$prefix$i* $path$prefix$i
done
However, this is not working. The wildcard seems not to be working and the expression is taken with a string. Note that the command works just fine in the terminal.
try this
`mv $path$prefix$i* $path$prefix$i`
Related
I'm running Centos 7. I need to have a cron job that moves everything from /media/tmp to /media/tv except the .grab and Transcode folders. Yesterday I thought that the following worked, but today it moves the Transcode folder as well.
mv -n /media/tmp/*!(Transcode)!(.grab) /media/tv/
I've found that the above does not work as a cron job as the '(' causes and error. I learned that I needed to escape those, but now I get
mv: cannot stat ‘/media/tmp/!(Transcode)!(.grab)’: No such file or directory
My current attempt at a bash script is
#!/bin/bash
mv -n '/media/tmp'/*!\(Transcode\)!\(.grab\) '/media/tv/'
My understanding is that the * is the problem, but using either ' or " on the file path doesn't seem to fix it like that post I found said it would.
Any ideas on how to get this to work correctly?
You're trying to use extglob, which may not be enabled for cron. I would avoid that option entirely, iterating over the glob with a negative ! regex match.
for file in /media/tmp/*; do
[[ ! "$file" =~ Transcode|\.grab$ ]] && mv -n "$file" /media/tv/
done
I'd just do it as something simple like (untested):
mkdir -p /media/tv || exit 1
for i in /media/tmp/*; do
case $(basename "$i") in
Transcode|.grab ) ;;
* ) mv -n -- "$i" /media/tv ;;
esac
done
I'm creating a very simple bash script that will check to see if the directory exists, and if it doesn't, create one.
However, no matter what directory I put in it doesn't find it!
Please tell me what I'm doing wrong.
Here is my script.
#!/bin/bash
$1="/media/student/System"
if [ ! -d $1 ]
then
mkdir $1
fi
Here is the command line error:
./test1.sh: line 2: =/media/student/System: No such file or directory
Try this
#!/bin/bash
directory="/media/student/System"
if [ ! -d "${directory}" ]
then
mkdir "${directory}"
fi
or even shorter with the parent argument of mkdir (manpage of mkdir)
#!/bin/bash
directory="/media/student/System"
mkdir -p "${directory}"
In bash you are not allow to start a variable with a number or a symbol except for an underscore _. In your code you used $1 , what you did there was trying to assign "/media/student/System" to $1, i think maybe you misunderstood how arguments in bash work. I think this is what you want
#!/bin/bash
directory="$1" # you have to quote to avoid white space splitting
if [[ ! -d "${directory}" ]];then
mkdir "$directory"
fi
run the script like this
$ chmod +x create_dir.sh
$ ./create_dir.sh "/media/student/System"
What the piece of code does is to check if the "/media/student/System" is a directory, if it is not a directory it creates the directory
I am trying to move all the arguments that are given when the script is run, to a RecycleBin directory. I am setting RecycleBin to be a directory in my home folder using RecycleBin="$HOME/Recycled".
I then want to move all the arguments files / directories to the RecycleBin directory.
This is what I've got so far:
for i in $*
do
if [ $* -e ]
then
mv $i /path/to/RecycleBin/$*.`date +"%Y%m%d.%H%M%S"`
else
echo "The file does not exist"
fi
done
where .date +"%Y%m%d.%H%M%S" is appending the version (date command) of each file
and for i in $* is checking for all the arguments in the command.
Output will look something like this ./script.sh file1 file2 file3
- where 3 files are being moved into RecycleBin
This is not working as my loop function is incorrect.
Would appreciate help
Thanks
Pete
[ $* -e ]
That test should be this:
[ -e "$i" ]
Also in the mv command you should be using $i rather than $*. Personally I'd just get rid of the if statement entirely. mv will print out an error message if a file doesn't exist, no need to do it yourself.
To handle file names with spaces in them it's best practice to use "$#" in place of $*, and to surround your variable names with with quotes, like so:
for file in "$#"; do
mv "$file" "/path/to/RecycleBin/$file.$(date +%Y%m%d.%H%M%S)"
done
I have larger shell script which handles different things.
It will get it's own location by the following...
BASEDIR=`dirname $0`/..
BASEDIR=`(cd "$BASEDIR"; pwd)`
then BASEDIR will be used create other variables like
REPO="$BASEDIR"/repo
But the problem is that this shell script does not work if the path contains spaces where it is currently executed.
So the question is: Does exist a good solution to solve that problem ?
Be sure to double-quote anything that may contain spaces:
BASEDIR="`dirname $0`"
BASEDIR="`(cd \"$BASEDIR\"; pwd)`"
The answer is "Quotes everywhere."
If the path you pass in has a space in it then dirname $0 will fail.
$ cat quote-test.sh
#!/bin/sh
test_dirname_noquote () {
printf 'no quotes: '
dirname $1
}
test_dirname_quote () {
printf 'quotes: '
dirname "$1"
}
test_dirname_noquote '/path/to/file with spaces/in.it'
test_dirname_quote '/path/to/file with spaces/in.it'
$ sh quote-test.sh
no quotes: usage: dirname string
quotes: /path/to/file with spaces
Also, try this fun example
#!/bin/sh
mkdir -p /tmp/foo/bar/baz
cd /tmp/foo
ln -s bar quux
cd quux
cat >>find-me.sh<<"."
#!/bin/sh
self_dir="$(dirname $0)"
base_dir="$( (cd "$self_dir/.." ; pwd -P) )"
repo="$base_dir/repo"
printf 'self: %s\n' "$self_dir"
printf 'base: %s\n' "$base_dir"
printf 'repo: %s\n' "$repo"
.
sh find-me.sh
rm -rf /tmp/foo
Result when you run it:
$ sh example.sh
self: .
base: /tmp/foo
repo: /tmp/foo/repo
Quote your full variable like this:
REPO="$BASEDIR/repo"
There is no reliable and/or portable way to do this correctly.
See How do I determine the location of my script? as to why
The best answer is the following, which is still OS dependent
BASEDIR=$(readlink -f $0)
Then you can do things like REPO="$BASEDIR"/repo , just be sure to quote your variables as you did.
Works perfectly fine for me. How are you using REPO? What specifically "doesn't work" for you?
I tested
#!/bin/sh
BASEDIR=`dirname $0`/..
BASEDIR=`(cd "$BASEDIR"; pwd)`
REPO="$BASEDIR"/repo
echo $REPO
in a ".../a b/c d" directory. It outputs ".../a b/repo", as expected.
Please give the specific error that you are receiving... A "doesn't work" bug report is the least useful bug report, and every programmer absolutely hates it.
Using spaces in directory names in unix is always an issue so if they can be avoided by using underscores, this prevents lots of strange scripting behaviour.
I'm unclear why you are setting BASEDIR to be the parent directory of the directory containing the current script (..) and then resetting it after changing into that directory
The path to the directory should still work if it has ..
e.g. /home/trevor/data/../repo
BASEDIR=`dirname $0`/..
I think if you echo out $REPO it should have the path correctly assigned because you used quotes when assigning it but if you then try to use $REPO somewhere else in the script, you will need to use double quotes around that too.
e.g.
#!/bin/ksh
BASEDIR=`dirname $0`/..
$REPO="$BASEDIR"/repo
if [ ! -d ["$REPO"]
then
echo "$REPO does not exist!"
fi
Use speech marks as below:
BASEDIR=`dirname "${0}"`/..
I'm trying to get the contents of a directory using shell script.
My script is:
for entry in `ls`; do
echo $entry
done
However, my current directory contains many files with whitespaces in their names. In that case, this script fails.
What is the correct way to loop over the contents of a directory in shell scripting?
PS: I use bash.
for entry in *
do
echo "$entry"
done
don't parse directory contents using ls in a for loop. you will encounter white space problems. use shell expansion instead
for file in *
do
if [ -f "$file" ];then
echo "$file"
fi
done