Linux script Loop - linux

I want to create a loop in Linux script that will go thru the folders in one directory and will copy photos to one folder and will overwrite photos that have the same name. Can anyone point me in the write direction?

find /path/to/source -type f -exec cp -f {} /path/to/destination \;
Would that work? Keep in mind, that will overwrite files without asking.
If you want it to confirm with you before overwriting, use the -i flag (for interactive mode) in the cp command.

find /path/to/source -type f | xargs -I {} file {} | grep <JPEG or image type> | cut -d ":" -f1 | xargs -I {} cp -rf {} /path/to/destination
With this you can find tune your copy with selecting only the image type.

Actually, you need not to loop through folders for finding photos using script, find command will do that job for you.
Try using find with xargs and cp
find source_dir -type f -iname '*.jpg' -print0 | xargs -0 -I {} cp -f {} dest_dir
Replace *.jpg with format of your photo files. (e.g. *.png etc.)
Note the use of -f option of cp, since you want to overwrite photos with the same name

Related

How to make a FOR loop to move files to directory based on file extension

Im trying to sort thousands of files and put them in their own folder based on file extension. For example, JPG files to go into a JPG folder.
How can I create a for loop to address this?
What I have attempted to far:
# This listed out all the file extensions and the count for each extension:
find . -type f | rev | cut -d. -f1 | rev | tr '[:upper:]' '[:lower:]' | sort | uniq --count | sort -rn
#This was able to find all jpegs in the media folder
find /media -iname '*.jpg'
# This worked, however the MV command does not create the folder
find /media -iname '*.jpg' -exec mv '{}' /media/genesis/Passport/consolidated/jpg/ \; #
Im guessing that the for loop would be something like but I cant seem to figure it out:
for dir in 'find /media -iname "*.jpg"'; do
mkdir $dir;
mv $dir/*;
done
To find all the files of a particular extension and move then to a destination we can use find command as follows:
find . -name "*.jpg" -exec mv {} $destination/ \;
This being the critical logic, you can just create a for loop on top of this to iterate through all the known file extensions in your media folder
## List all the known extensions in your media folder.
declare -a arr=("jpg" "png" "svg")
## Refer question 1842254 to get all the extentsions in your folder.
## find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
## now loop through the above array
for i in "${arr[#]}"
do
echo "$i"
## Create a directory based on file extension
destination="$i"
mkdir $destination
find /media -iname "*.$i" -exec mv {} $destination/ \;
done
Note that you can change your destination to be whatever you want. I just left it in the same directory.
Here is an executable shell script for your reference: https://onlinegdb.com/NEQSpojhM

Find/list only file types recursive in a directory

how can i search for files and give only a list of mimes or types out.
example:
dir
-file1.pdf
-file2.pdf
-dir2
--file3.png
--file4.pdf
wished output:
pdf
png
Edit
Found also a solution, but does not make a difference between upper and lowercase and also not .peng and .png
find . -type f -printf '%f\n' | sed 's/^.*\.//' | sort -u
Use find's -exec option together with any solution that extracts the extension. Then pipe through sort -u to remove duplicates.
find dir -type f -exec bash -c 'printf %s\\n "${###*.}"' x {} + | sort -u
Files without extensions will be listed too. To filter them out add the option -name '*\.*' before -exec.

Linux: find a file in a directory, backup it with another name, replace it

In Linux I'm trying to find a file in a directory, backup it with another name and, then, replace it with another one.
I tried the first two actions with these commands
find foldername -name filename.html; -exec sed -i .bak;
but it's says
bash: -exec: command not found
Try this:
find foldername -name filename.html -exec cp -vp {}{,.bak} \; -exec truncate -s 0 {} \;
This uses find's exec option like it looks like you tried to use. Then cp copies the file (specified with {}) and appends .bak to the copy and preserves what it can with the p option:
preserve the specified attributes (default:
mode,ownership,timestamps), if possible additional attributes:
context, links, xattr, all
This leaves the original file in place as well.
You can do the following:
find . -name 'FILE_PATTERN_HERE' | xargs -I file_name cp file_name file_name.bkp
You can pipe the output of find command to cp using xargs. Here file_name acts as the output of find.
Example
find . -name 'logback.xml*'
Output:
./logback.xml
./apache-cassandra-3.11.1/conf/logback.xml
After running the command
find . -name 'logback.xml*' | xargs -I file_name cp file_name file_name.bkp
find . -name 'logback.xml*'
Output:
./logback.xml
./apache-cassandra-3.11.1/conf/logback.xml
./apache-cassandra-3.11.1/conf/logback.xml.bkp
./logback.xml.bkp

Linux copying subdirectories with same name to a file

Imagine a directory structure that looks like :
/a1/b1/c1/O
/a1/b2/c2/O
/a1/b3/c3/O
how do I copy all content of the "O" directory to one file?
I've tried cp -r /a1/*/O ~/O and it fails
One more glob pattern needed. Use:
cp -r /a1/*/O/* ~/O
OR to make this command work for any depth use find:
find /a1 -type d -name 'O' -print0 | xargs -0 -I % cp -r %/* ~/O

Linux: Find a List of Files in a Dictionary recursively

I have a Textfile with one Filename per row:
Interpret 1 - Song 1.mp3
Interpret 2 - Song 2.mp3
...
(About 200 Filenames)
Now I want to search a Folder recursivly for this Filenames to get the full path for each Filename in Filenames.txt.
How to do this? :)
(Purpose: Copied files to my MP3-Player but some of them are broken and i want to recopy them all without spending hours of researching them out of my music folder)
The easiest way may be the following:
cat orig_filenames.txt | while read file ; do find /dest/directory -name "$file" ; done > output_file_with_paths
Much faster way is run the find command only once and use fgrep.
find . -type f -print0 | fgrep -zFf ./file_with_filenames.txt | xargs -0 -J % cp % /path/to/destdir
You can use a while read loop along with find:
filecopy.sh
#!/bin/bash
while read line
do
find . -iname "$line" -exec cp '{}' /where/to/put/your/files \;
done < list_of_files.txt
Where list_of_files.txt is the list of files line by line, and /where/to/put/your/files is the location you want to copy to. You can just run it like so in the directory:
$ bash filecopy.sh
+1 for #jm666 answer, but the -J option doesn't work for my flavor of xargs, so i chaned it to:
find . -type f -print0 | fgrep -zFf ./file_with_filenames.txt | xargs -0 -I{} cp "{}" /path/to/destdir/

Resources