Reputation: 2654
My root folder structure is like this:
My Family - Holiday My Birthday[15.11] Name-Name[1] Name1 Name2 ...
Now, I want every folder which contains a .info
file to move to another directory.
Here's my code:
#!/bin/sh
for folder in *
do
echo $folder
if [ -e "$folder/*.info" ]
then
echo $folder
mv $folder ./Finished
fi
done
The echoes are only for testing.
I have found that every time a non-escaped character is in the name that the if
is failing. How can I fix this?
Upvotes: 1
Views: 168
Reputation: 46816
Bash wants you to quote your variables.
#!/bin/bash
if [[ "$1" = "-v" ]]; then
Verbose=true
vopt="-v"
shift
else
Verbose=false
vopt=""
fi
for folder in *; do
$Verbose && printf "%s" "$folder"
if [[ -e "$folder/*.info" ]]; then
if mv "$vopt" "$folder" ./Finished/; then
$Verbose && echo -n " ... done"
fi
fi
$Verbose && echo ""
done
Note that it's a good idea to end your target directory with a slash. That way, if for some reason the Finished
directory disappears, you'll get an error rather than silently renaming the first $folder to Finished, then moving all the other matches into the first match.
Note also that I'm using printf
for some of the debugging output just in case one of your $folder
s starts with a hyphen.
UPDATE #1: you now have debugging controlled with the -v
option.
UPDATE #2: I just realized that you are checking for the existence of *.info
, literally. Note:
ghoti@pc ~$ mkdir foo
ghoti@pc ~$ touch foo/\*.info
ghoti@pc ~$ ls -la foo
total 0
-rw-r--r-- 1 ghoti ghoti 0 8 Aug 07:45 *.info
drwxr-xr-x 3 ghoti ghoti 102 8 Aug 07:45 .
drwx------+ 10 ghoti ghoti 340 8 Aug 07:44 ..
ghoti@pc ~$ [[ -e "foo/*.info" ]] && echo yes
yes
ghoti@pc ~$ mv foo/\*.info foo/bar.info
ghoti@pc ~$ [[ -e "foo/*.info" ]] && echo yes
ghoti@pc ~$
If what you really want to find is "any file ending in .info", then [[ -e
is not the way to go. Pls confirm before I work more on this answer. :)
UPDATE #3:
Here's a version that finds moves your folder if the folder conains any .info file. Note that this does not grep the output of ls
.
[ghoti@pc ~/tmp1]$ cat doit
#!/bin/bash
if [[ "$1" = "-v" ]]; then
Verbose=true
vopt="-v"
shift
else
Verbose=false
vopt=""
fi
for folder in *; do
infofile="$(
if [[ -d "$folder" ]]; then
cd "$folder"
for file in *.info; do
if [[ -f "$file" ]]; then
echo "$file"
break
fi
done
fi
)"
if [[ -f "$folder/$infofile" ]]; then
mv "$vopt" "$folder" ./Finished/
elif $Verbose; then
printf "%s ... skipped\n" "$folder"
fi
done
[ghoti@pc ~/tmp1]$ find . -print
.
./doit
./baz
./foo
./foo/bar.info
./Finished
[ghoti@pc ~/tmp1]$ ./doit -v
Finished ... skipped
baz ... skipped
doit ... skipped
foo -> ./Finished/foo
[ghoti@pc ~/tmp1]$
Upvotes: 6
Reputation: 4446
Try this:
PATH_TO_FOLDER="/YOUR_FOLDER"
for f in `ls $PATH_TO_FOLDER`;
do
# Check filename
if [ $(echo $f | grep -Ec ".info$") -ne 1 ]
then
echo "We don't care"
else
## move the file
fi
done
Upvotes: -1
Reputation: 212198
The primary issue is that you cannot use test -e *.info
. You can parse the output of ls to check for the file. There are issues with parsing ls, but they are much less significant than many people make them out to be. If you do not allow newlines in filenames, the following should work:
#!/bin/sh
for dir in *; do
if ls -f "$dir" | grep -q '\.info$'; then
mv "$dir" ./Finished
fi
done
Do note that it is essential that no filenames have an embedded newline, since this will incorrectly identify a file named foo.info\nbar
as if there were a single file named foo.info
. In reality, this is unlikely to be a significant issue. If this is an issue, you will not want to use the shell for this, although you could do:
#!/bin/sh
for dir in *; do
for f in "$dir"/*; do
case "$f" in
*.info) mv "$dir" ./Finished; break;;
esac
done
done
Upvotes: 3