Copy all photos on an entire drive in bash? [closed] - linux

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have a drive that mounts at /run/media/jeremy/MONSTER that has a ton of old backups of aperture libraries, iPhoto libraries, and general backups of home directories from the years.
I'd like to track down every gif, jpg, jpeg, and cannon raw file and copy them to /run/media/jeremy/1.4t_Video/photos and optimally have them given a unique name based on the file creation date. I assume bash is up to the task, but not sure how to go about it.

find /run/media/jeremy/MONSTER \( -iname \*.gif -o -iname \*.jpg -o -iname \*.jpeg \) -exec cp {} /run/media/jeremy/1.4t_Video/photos/ \;
this should find all files ending in those extensions and copies them over to /run/media/jeremy/1.4t_Video/photos/
if you want to add more extensions just use -o -iname *.

You could use a script like this:
#!/bin/bash
serial=0
find /run/media/jeremy/MONSTER \( -iname \*.gif -o -iname \*.jpg -o -iname \*.jpeg -o -iname \*.cr2 \) -print0 |
while read -r -d '' f; do
# Get its extension, like "jpg" or "cr2"
ext=${f##*.}
# Get its date of creation like "2012-01-07 11:06:45"
datetime=$(stat --printf="%w" "$f" | sed 's|\..*||')
# Formulate a new name
new="/output/dir/${datetime}-${serial}.${ext}"
# Show what we came up with
echo Would copy $f to $new
# cp "$f" "$new"
((serial++))
done
At the moment it does nothing, it just shows you what it would do. Uncomment the 3rd to last line, by removing the # in front of cp if it looks correct. Please make a backup first and test with a small number of files...
Sample Output
Would copy ./b.jpg to /output/dir/2016-02-11 10:40:58-0.jpg
Would copy ./mosaic/0.jpg to /output/dir/2016-02-08 12:36:06-1.jpg
Would copy ./mosaic/1.jpg to /output/dir/2016-02-08 12:36:07-2.jpg
Would copy ./mosaic/10.jpg to /output/dir/2016-02-08 12:36:12-3.jpg
Would copy ./mosaic/100.jpg to /output/dir/2016-02-08 12:36:41-4.jpg
Would copy ./mosaic/101.jpg to /output/dir/2016-02-08 12:36:42-5.jpg
Would copy ./mosaic/102.jpg to /output/dir/2016-02-08 12:36:42-6.jpg
Would copy ./mosaic/103.jpg to /output/dir/2016-02-08 12:36:42-7.jpg

Related

Create file in all subdirectories [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm trying to create a file called 1 in all subdirectories.
e.g the main directory is abc and sub-directories are abc/xyz, abc/ghi/123
It must contain a full path and file name.
You can do something along the lines of
for d in $(find abc -type d); do
touch "$d"/1
done
Use:
find abc -type d -print0 | while IFS= read -r -d '' dir; do
readlink -f "$dir"/1 > "$dir"/1
done
It finds all directories recursive in directory named abc
For each directory found, it read it to "dir" variable
readlink -f shows full path to a path "$dir"/1
> "$dir"/1 writes to the file "$dir"/1, truncates it before writing, creates if it does not exists
The -print0 and -d '' are for handling spaces and newlines in directory names.
And a version using xargs:
find abc -type d -print0 | xargs -0 -n1 -- sh -c 'readlink -f "$1"/1 > "$1"/1` --
But we can also use find's -exec, which should probably be the fastest:
find abc -type d -exec sh -c 'readlink -f "$1"/1 > "$1"/1' -- {} \;

find *.tar then extract and delete the files [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to find a tar file, extract the files then remove all the extracted files - I'm able to perform the find and extraction or find the file and remove it but I'm not able to string all three together.
Here is my best attempt below. It runs without error but doesn't delete the extracted files so I'm stuck on how to remove the files I've extracted to the current directory.
find ~ -name '*.tar' | xargs tar -xf && rm -f
I tried extracting the tar to another directory then removing the directory but couldn't get it to work while using xargs. I've tried searching quite a few different areas but couldn't find anything so I appreciate the help.
The && ends the pipeline, it's not part of the xargs command.
You can just run the commands using the -exec option to find:
find ~ -name '*.tar' -exec tar -xf {} \; -exec rm -f {} \;
To run two or multiple commands with xargs:
find ~ -name '*.tar' | xargs -I {} sh -c 'tar -xf {} && rm -f {}'
Only after successfully unpacking the tar file is deleted.

linux shell script to copy directory tree and link files [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I would like to be able to create a copy of a directory tree and soft link the files on it.
For example, from
/home/user/origin/a/sub/file.txt
I would like to get
/home/user/destination/a/sub/file.txt
being this one a link to the original file.txt.
I tested with
find /home/user/origin/ -type d -printf "mkdir -vp '/home/user/destination%p'\n" -o -type f -printf "ln -vs '%p' '/home/user/destination%p'\n" | sh
but it has two problems:
I'd like to copy from origin to destination, and it copies from origin to /home/user/destination/home/user/origin. It is not a biggie, as I can move that afterwards
If the file name is something like
In Fifty Years We'll All Be Chicks.txt
It stops working because the '.
Assuming I understand what you're trying to do, it seems easier to just use -exec
find /home/user/origin/ \
-type d -exec sh -c 'mkdir -v "/home/user/destination/${0#/home/user/origin/}"' {} \; \
-o \
-type f -exec sh -c 'ln -vs "$0" "/home/user/destination/${0#/home/user/origin/}"' {} \;
Note -or having lower precedence than the implied -and's is important here.

finding files and moving their folders [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 9 years ago.
Improve this question
I have a huge number of text files, organized in a big folder tree, on Debian Linux. What I need is to find all text files having a specific name pattern and then move the containing folder to a destination.
Example:
/home/spenx/src/a12/a1a22.txt
/home/spenx/src/a12/a1a51.txt
/home/spenx/src/a12/a1b61.txt
/home/spenx/src/a12/a1x71.txt
/home/spenx/src/a167/a1a22.txt
/home/spenx/src/a167/a1a51.txt
/home/spenx/src/a167/a1b61.txt
/home/spenx/src/a167/a1x71.txt
The commands:
find /home/spenx/src -name "a1a2*txt"
mv /home/spenx/src/a12 /home/spenx/dst
mv /home/spenx/src/a167 /home/spenx/dst
The result:
/home/spenx/dst/a12/a1a22.txt
/home/spenx/dst/a167/a1a22.txt
Thank you for your help.
SK
combination of find, dirname and mv along with xargs should solve your problem
find /home/spenx/src -name "a1a2*txt" | xargs -n 1 dirname | xargs -I list mv list /home/spenx/dst/
find will fetch list of files
dirname will extract path of file. Note that it can only take one argument at a time
mv will move source directories to destination
xargs is the key to allow output of one command to be passed as arguments to next command
For details of options used with xargs, refer to its man page of just do man xargs on terminal
You can execute:
find /home/spenx/src name "a1a2*txt" -exec mv {} /home/spenx/dst \;
Font: http://www.cyberciti.biz/tips/howto-linux-unix-find-move-all-mp3-file.html
Create this mv.sh script in the current directory that will contain this:
o=$1
d=$(dirname $o)
mkdir /home/spenx/dst/$d 2>/dev/null
mv $o /home/spenx/dst/$d
Make sure it is executable by this command:
chmod +x mv.sh
Next call this command:
find /home/spenx/src -name "a1a2*txt" -exec ./mv.sh {} \;
find /home/spenx/src -name "a1a2*txt" -exec mv "{}" yourdest_folder \;
There's probably multiple ways to do this, but, since it seems you might have multiple matches in a single directory, I would probably do something along this line:
find /home/spenx/src -name "a1a2*txt" -print0 | xargs -0 -n 1 dirname | sort -u |
while read d
do
mv "${d}" /home/spenx/dst
done
It's kind of long, but the steps are:
Find the list of all matching files (the find part), using -print0 to compensate for any names that have spaces or other odd characters in them
extract the directory part of each file name (the xargs ... dirname part)
sort and uniquify the list to get rid of duplicates
Feed the resulting list into a loop that moves each directory in turn

Recursive copy of a specific file type maintaining the file structure in Unix/Linux? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I need to copy all *.jar files from a directory maintaining the folder structure of the parent directories. How can I do it in UNIX/Linux terminal?
The command cp -r *.jar /destination_dir is not what I am looking for.
rsync is useful for local file copying as well as between machines. This will do what you want:
rsync -avm --include='*.jar' -f 'hide,! */' . /destination_dir
The entire directory structure from . is copied to /destination_dir, but only the .jar files are copied. The -a ensures all permissions and times on files are unchanged. The -m will omit empty directories. -v is for verbose output.
For a dry run add a -n, it will tell you what it would do but not actually copy anything.
If you don't need the directory structure only the jar files, you can use:
shopt -s globstar
cp **/*.jar destination_dir
If you want the directory structure you can check cp's --parents option.
If your find has an -exec switch, and cp an -t option:
find . -name "*.jar" -exec cp -t /destination_dir {} +
If you find doesn't provide the "+" for parallel invocation, you can use ";" but then you can omit the -t:
find . -name "*.jar" -exec cp {} /destination_dir ";"
cp --parents `find -name \*.jar` destination/
from man cp:
--parents
use full source file name under DIRECTORY
tar -cf - `find . -name "*.jar" -print` | ( cd /destination_dir && tar xBf - )
If you want to maintain the same directory hierarchy under the destination, you could use
(cd SOURCE && find . -type f -name \*.jar -exec tar cf - {} +) \
| (cd DESTINATION && tar xf -)
This way of doing it, instead of expanding the output of find within back-ticks, has the advantage of being able to handle any number of files.
find . -name \*.jar | xargs cp -t /destination_dir
Assuming your jar filenames do not contain spaces, and your cp has the "-t" option. If cp can't do "-t"
find . -name \*.jar | xargs -I FILE cp FILE /destination_dir

Resources