Bash script not moving files - linux

I have a bash script that is designed to run in a Linux directory that contains only a collection of image files and video files of varying formats. Once executed, the script looks to see if the Vids and Pics subdirectories exist, and if not, creates them. Then all of the image files are supposed to get moved into Pics and the video files moved into Vids.
But when the script executes the directories get created but none of the files are moved into them.
Any bash experts out there that can take a quick look and suggest a fix?
#!/bin/bash
echo "This script will check for the existence of 'Vids' and 'Pics' subdirectories and create them if they do not exist. It will then move all image files into 'Pics' and all video files into 'Vids'. Do you wish to proceed? (y/n)"
read proceed
if [ $proceed == "y" ]; then
if [ ! -d "Vids" ]; then
mkdir Vids
fi
if [ ! -d "Pics" ]; then
mkdir Pics
fi
find . -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o -name "*.gif" -exec mv {} Pics/ \;
find . -name "*.mp4" -o -name "*.avi" -o -name "*.mkv" -o -name "*.wmv" -exec mv {} Vids/ \;
echo "Image files have been moved to 'Pics' and video files have been moved to 'Vids'."
else
echo "Exiting script."
fi
I named the script test.sh and gave it execute permission. When I ran the script, it was run in a directory with a large number of both image and video files. The script asked me if I wanted to continue. When I said yes, it said the directories Vids and Pics was created and all the files moved into them. The script then ends. But none of the files have been moved, although the directories Vids and Pics was created.

The implicit AND operator has higher precedence than -o, so your command is equivalent to:
find . -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o \( -name "*.gif" -exec mv {} Pics/ \; \)
so it only performs -exec for *.gif, not the other extensions. You need to put parentheses around all the -name expressions.
find . \( -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o -name "*.gif" \) -exec mv {} Pics/ \;

Related

Find different types of files and move to a specific directory

Finding *.mkv and *.mp4 works
find /home6/movies/ -name '*.mp4' -o -name '*.mkv'
but moving them for some reason partially fails and moves only mkv files
find /home6/movies/ -name '*.mp4' -o -name '*.mkv' -exec mv {} /home6/archive/ \;
Am I using an incorrect find switch "-o" for this task?
Looks like you need to surround the or expression in parentheses so the exec applies to both matches.
This is a similar question: `find -name` pattern that matches multiple patterns
find /home6/movies/ \( -name '*.mp4' -o -name '*.mkv' \) -exec mv {} /home6/archive/ \;

What the best way to delete files by extension?

I am looking the best way to delete files from directory by extension.
I am planning to do it by date. But now, i am testing how it works.
This:
dir=/tmp/backup/
mask="jpeg jpg png gif bmp pdf"
for i in $mask; do
find $dir -name "*.$i" -type f -delete
done
Or this ?
find $dir \( -name "*.jpeg" -o -name "*.jpg" -o -name "*.png" \
-o -name "*.gif" -o -name "*.bmp" -o -name "*.pdf" \) -type f -delete
I wan to do it with min resources of machine and operation system. Maybe you know other ways to do it. Because i will delete one year old files. And it can call lags. Thanks.
You can just use:
# to ensure it doesn't return *.jpg if there is no .jpg file
shopt -s nullglob
# list all matching extension filea
echo *.{jpeg,jpg,png,gif,bmp,pdf}
When you are satisfied with the output, just replace echo by rm
However if you want to make use of a variable then store all extensions in a variable then use it like this with find command:
mask="jpeg jpg png gif bmp pdf"
find . -type f -regextype posix-extended -regex ".*\.("${mask// /|}")"

How to clean up folders efficiently using shell script

I am using a directory structure with various folders. There are new files created daily in some of them.
I have created some programs to clean up the directories, but I would like to use a shell script to make it more efficient.
Therefore I would like to store an "archiving.properties" file in every folder that needs to be cleaned up. The properties file should contain the following variables
file_pattern="*.xml"
days_to_keep=2
Now my clean up routine should:
find all properties files
delete all files that match the file name pattern (file_pattern) and that are older then the defined number of days (days_to_keep) in the directory where the properties file was found.
So my question is how can I do this in the most efficient way?
find . -type f -name "archiving.properties" -print
find . -type f -name "<file_pattern>" -mtime +<days_to_keep> -delete
currently I was trying the following in a single folder. It prints out the command correctly, but it is not executed.
#!/bin/bash
. archiving.properties
find . -type f -name "*.xml" -mtime +1 -exec rm -rf {} \;
echo " find . -type f -name \"${file_pattern}\" -mtime +${days_to_keep} -exec rm -rf {} \;"
Result is: find . -type f -name "*.xml" -mtime +1 -exec rm -rf {} \;
Thanks for your help in advance.
I got a final result
echo "start deleting files in " $(pwd) " ... "
#filename of the properties
properties="clean_up.properties"
#find all properties files
for prop in $(find . -type f -name $properties);do
#init variables
file_pattern="*._html"
days_to_keep=14
#load the variables from the properties file
. "$prop"
#define the folder of the properties file
folder=${prop%?$properties}
#remove all files matching the parameters in the folder where the properties were found
echo ">>> find $folder -type f -name \"${file_pattern}\" -mtime +${days_to_keep} -exec rm -f {} \;"
find $folder -type f -name "${file_pattern}" -mtime +${days_to_keep} -exec rm -f {} \;
done
echo "... done"

The find Command with -exec Does Not Run the -exec Command

I want to write a simple command to cleanup my project files, so I used:
find . -type f -name "*.o" -o -name "*.a" -o -name "*.ko" -exec rm '{}' +
Oddly it didn't work. And when I removed " -exec rm '{}' +" I could see that it dumped the files out the terminal, so it looks like my expression is correct. I even tried changing "'{}' +" to "'{}' \;", but this also didn't work. I also tried replacing rm with echo but nothing was displayed in the terminal. Am I doing something wrong?
Using Ubuntu 12.04.
Try using it like this:
find . -type f \( -name "*.o" -o -name "*.a" -o -name "*.ko" \) -exec rm -f {} \;
When using multiple files with find combined with exec it often only acts on the last filename.

Include folder name in renaming a file in linux

I've already used that command to rename the files in multiple directories and change JPG to jpg, so I have consistency.
find . -name '*.jpg' -exec sh -c 'mv "$0" "${0%.JPG}$.jpg"' {} \;
Do you have any idea how to change that to include the folder name in the name of the file
I am executing that in a folder that contains about 2000 folders (SKU's) or products ... and inside every SKU folder, there are 9 images. 1.jpg 2.jpg .... 9.jpg.
So the bottom-line is I have 2000 images with name 1.jpg, 2.jpg ... 9.jpg. I need those files to be unique, for example:
folder-name-1.jpg ... folder-name.2.jpg ... so on, in every folder.
Any help will be appreciated.
For example I can do as follows:
$ find . -iname '*.jpg' | while read fn; do name=$(basename "$fn") ; dir=$(dirname "$fn") ; mv "$fn" "$dir/$(basename "$dir")-$name" ;done
./lib/bukovina/version.jpg ./lib/bukovina/bukovina-version.jpg
./lib/bukovina.jpg ./lib/lib-bukovina.jpg
You can use fine one-liner:
find . -name '*.jpg' -execdir \
bash -c 'd="${PWD##*/}"; [[ "$1" != "$d-"* ]] && mv "$1" "./$d-$1"' - '{}' \;
This command uses safe approach to check whether image name is already not prefixed by the current directory name. You can run it multiple times also and image name won't be renamed after first run.
To get the folder name of a file you can do $(basename $(dirname ${FILE})), where ${FILE} is a path that may be relative but must contain at least one folder before the file name in it. This should not be a problem with find. If it is, just run it from one directory up.
find . -name '*.jpg' -exec sh -c 'mv "$0" "$(basename $(dirname $0))-${0%.JPG}$.jpg"' {} \;
Or, if you have JPEGs in your current directory:
find ../<dirname> -name '*.jpg' -exec sh -c 'mv "$0" "$(basename $(dirname $0))-${0%.JPG}$.jpg"' {} \;

Resources