LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   extra help with bash (https://www.linuxquestions.org/questions/linux-software-2/extra-help-with-bash-4175518367/)

nyloc 09-12-2014 10:27 AM

extra help with bash
 
I've been reading a lot of tutorials but cant find exactly what I want.
I want to check if there are any JPG or jpeg files before I process them with ImageMagik.
All I have found is
if [ -f filename ]
which only checks for one file, I want to check for *.JPG but using if [ -f *.JPG ] fails if more than one JPG file exists.

Keefaz big thanks, that script for identify worked well and after changing $h > 800 to $w >= $h I got rid of the portrait orientated pics as well as the small ones. It takes 10 - 15 minutes to process approx 12500 files and I can live with that especially as my box is about 7 years old.

linosaurusroot 09-12-2014 11:28 AM

Code:

for i in *.JPG *.jpg *.JPEG *.jpeg
do
  [ -f $i ] && do_thing_here_with $i
done


schneidz 09-12-2014 11:54 AM

i would do something like this:
Code:

[schneidz@hyper ~]$ find /var/www/html/beat-la/photos/ -exec file -i '{}' \;
/var/www/html/beat-la/photos/dscf0117.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0138.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0139.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0118.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0169.jpg: image/jpeg; charset=binary
...


nyloc 09-12-2014 01:11 PM

Oops I haven't explained my problem properly. I want to make all JPG and jpeg files jpg files. At the moment I do "rename JPG jpg *.JPG" (same for jpeg) and ignore the error message when there are no files to be changed. I would much prefer to have the rename in some sort of test.

Second question is to do with tidying up the file names. The script I found uses tr so I have ended up with this bit of code

image3=`echo "$image2" | tr " " "_"`
if [ "$image3" != "$image1" ]; then
mv "$image1" "$image3"
fi

But I really would like to be able to do the test first. Anyone got any alternatives ?

keefaz 09-12-2014 03:04 PM

I am not a sed specialist but...
Code:

image3=$(echo "$image1" | sed -e 's/ /_/g' -e 's/\(.*\)\..\{3,4\}$/\1.jpg/')

[ ! -f "$image3" ] && mv "$image1" "$image3"

(used $image1 as I don't know what $image2 is)

nyloc 09-12-2014 08:06 PM

Looks like your sed knowledge is better than my typing ability (image2 should read image1). Still have the issue of doing the test after the change, which I was taught is bad programming.
If it helps you with sed while searching script tutorials I came across this
# badname.sh
# Delete filenames in current directory containing bad characters.

for filename in *
do
badname=`echo "$filename" | sed -n /[\+\{\;\"\\\=\?~\(\)\<\>\&\*\|\$]/p`
# badname=`echo "$filename" | sed -n '/[+{;"\=?~()<>&*|$]/p'` also works.
# Deletes files containing these nasties: + { ; " \ = ? ~ ( ) < > & * | $
#
echo "rm " "$badname"
# rm $badname 2>/dev/null
# ^^^^^^^^^^^ Error messages deep-sixed.
done

but that doesn't solve the issue of I would rather do the test for spaces (and/or other dodgy characters) before changing the file name.

keefaz 09-12-2014 09:21 PM

Test for spaces doesn't matter as long as you just manipulate the file name
After you finish the name change, you just test with -f if file exists before doing the actual rename

PS: thanks for the sed examples, have to dig it a little more

nyloc 09-12-2014 10:17 PM

I could get silly and say :- but, but, but, even COBOL lets you say
IF filename INCLUDES a space THEN PERFORM the change
However I know shell scripting is not compiled and therefore is limited in what can be done.
Would it be possible to write a bash function along the lines of

Function Includes(filename)
local respone = false
move filename to an array of single characters the length of filename # this line is the tricky bit
for cnt = 1 , length of filename
do
if array[cnt] = " "
then
response = true
fi
od
return response

I can see issues with the above code already, such as it probably should return true
as soon as it finds a space. More importantly if I was to write that then it would seem
sensible to change the space characters there and return the new file name and then I wouldn't
need the line with tr in it.

ps how do stop the rename getting errors?

keefaz 09-13-2014 04:56 AM

You can do the space test more easily, bash has reg exp matching function

Code:

name="this is a name with spaces"

if [[ $name =~ " " ]]; then
  echo "yes I have spaces"
else
  echo "no, I haven't any space"
fi


nyloc 09-13-2014 06:56 AM

My other issue is I need a "move_all_but *.jpg to_somewhere_else" command. At the moment I am doing

mkdir $tmp_dir
mkdir $oth_dir
mv *.jpg $tmp_dir
mv *.* $oth_dir
mv $tmp_dir/* .
rmdir $tmp_dir

which looks really ugly to me.
Can anyone suggest a more elegant solution?

keefaz 09-13-2014 10:23 AM

You can use bash GLOBIGNORE env variable to ignore .jpg files, something like:

Code:

GLOBIGNORE="*.jpg"
mv * $dir

then all files but jpgs are moved to $dir

schneidz 09-13-2014 11:12 AM

Quote:

Originally Posted by schneidz (Post 5236889)
i would do something like this:
Code:

[schneidz@hyper ~]$ find /var/www/html/beat-la/photos/ -exec file -i '{}' \;
/var/www/html/beat-la/photos/dscf0117.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0138.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0139.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0118.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0169.jpg: image/jpeg; charset=binary
...


since your filenames are inconsistent to me it makes better sense to use the mime-type (file -i) to figure out the actual file type.

this worx for me:
Code:

[schneidz@hyper jamtat]$ file /var/www/html/beat-la/photos/*
/var/www/html/beat-la/photos/dscf0102.jpg:      JPEG image data, JFIF standard 1.01
/var/www/html/beat-la/photos/dscf0133.jpg:      JPEG image data, JFIF standard 1.01
/var/www/html/beat-la/photos/dscf0143.jpg:      JPEG image data, JFIF standard 1.01
/var/www/html/beat-la/photos/hello-world.jpg:  ASCII text
/var/www/html/beat-la/photos/this is a picture: JPEG image data, JFIF standard 1.01
[schneidz@hyper jamtat]$ find /var/www/html/beat-la/photos/ -exec sh -c "file -i '{}' | grep image.*charset=binary$" \; -exec sh -c 'filename="${0##*/}"; ln -sf "$0" bak/`echo $filename | tr " " "-"`' {} \;
/var/www/html/beat-la/photos/dscf0143.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/this is a picture: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0102.jpg: image/jpeg; charset=binary
/var/www/html/beat-la/photos/dscf0133.jpg: image/jpeg; charset=binary
[schneidz@hyper jamtat]$ ll bak
total 0
lrwxrwxrwx. 1 schneidz schneidz 38 Sep 13 14:37 dscf0102.jpg -> /var/www/html/beat-la/photos/dscf0102.jpg
lrwxrwxrwx. 1 schneidz schneidz 38 Sep 13 14:37 dscf0133.jpg -> /var/www/html/beat-la/photos/dscf0133.jpg
lrwxrwxrwx. 1 schneidz schneidz 38 Sep 13 14:37 dscf0143.jpg -> /var/www/html/beat-la/photos/dscf0143.jpg
lrwxrwxrwx. 1 schneidz schneidz 43 Sep 13 14:37 this-is-a-picture -> /var/www/html/beat-la/photos/this is a picture


nyloc 09-13-2014 07:59 PM

The script is getting better, processed about 30000 files in 16 minutes yesterday.
I like the idea of GLOBIGNORE.
So will have to do some more testing today.
I'm getting really really bored with two things, one - spending what seems like hours going through tutorials and not finding what I need, two Hello World !

nyloc 09-13-2014 08:14 PM

Keefaz there is a slight bug in your GLOBIGNORE example. It needs mv *.* $dir otherwise it tries to move $dir into a subdirectory of itself.

schneidz 09-13-2014 09:59 PM

Quote:

Originally Posted by nyloc (Post 5237491)
Keefaz there is a slight bug in your GLOBIGNORE example. It needs mv *.* $dir otherwise it tries to move $dir into a subdirectory of itself.

what if the dir name is dir.name ?


All times are GMT -5. The time now is 11:45 AM.