Find in file and then move that file using Linux? [closed] - linux

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 want to be able to find files that contain certain strings and the move that list of files to directory X
I can use this command to find the files
find . -iname 'commaus*' | xargs grep '>24901<' -sl
and this command to move files
mv * /home/user/scripts/xslt
But is there a way to combine these commands so that the found files are moved.
I have seen similar joined find/action commands such as
find /home/user -name property_images -ok rm -f {} \;
but following this structure is returning an error
find . -iname 'commaus*' | xargs grep '>24901<' -sl -ok mv {} /home/user/scripts/xslt;

Use a loop. In this case, try:
for i in `find . -iname 'commaus*' | xargs grep '>24901<' -sl`; do mv "$i" /home/user/scripts/xslt/; done
Very hackish, but it should work.

you can do this by wrapping it in a for loop
for i in `find /path/to/search -iname 'optionalfilename' -exec grep -H -m1 '>24901<' {} \; | awk -F: '{print $1}'
do
mv $i /path/to/new/location
done
This will not work as expected if filenames contain spaces or colons

Also might be able to try (without loop):
find . -iname 'commaus*' | grep '>24901<' -sl -ok | xargs mv -t /home/user/scripts/xslt

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.

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

List all graphic image files with find? [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 2 years ago.
Improve this question
There are many types of graphic images in this huge archive such as .jpg, .gif, .png, etc. I don't know all the types. Is there a way with 'find' to be able to have it list all the graphic images regardless of their dot extension name? Thanks!
This should do the trick
find . -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image'
example output:
./navigation/doc/Sphärische_Trigonometrie-Dateien/bfc9bd9372f650fd158992cf5948debe.png: PNG image
./navigation/doc/Sphärische_Trigonometrie-Dateien/6564ce3c5b95ded313b84fa918b32776.png: PNG image
./navigation/doc/subr_1.jpe: JPEG image
./navigation/doc/Astroanalytisch-Dateien/Gamma.gif: GIF image
./navigation/doc/Astroanalytisch-Dateien/deltaS.jpg: JPEG image
./navigation/doc/Astroanalytisch-Dateien/GammaBau.jpg: JPEG image
The following suits me better since in my case I wanted to pipe this list of files to another program.
find . -type f -exec file --mime-type {} \+ | awk -F: '{if ($2 ~/image\//) print $1}'
If you wanted to tar the images up (as someone in the comments) asked
find . -type f -exec file --mime-type {} \+ | awk -F: '{if ($2 ~/image\//) printf("%s%c", $1, 0)}' | tar -cvf /tmp/file.tar --null -T -
find . -type f -exec file {} \; | grep -o -P '^.+: \w+ image'
should even be better.
Grepping or using awk for "image" only will not do it. PSD-files will be identified by "Image" with a capital "I" so we need to improve the regexp to either be case insensitive or also include the capital I. EPS-files will not contain the word "image" at all so we need to also match for "EPS" or "Postscript" depending on what you want. So here is my improved version:
find . -type f -exec file {} \; | awk -F: '{ if ($2 ~/[Ii]mage|EPS/) print $1}'
Update (2022-03-03)
This is a refined version with the following changes:
Remove xargs.
Support filenames which contains : based on 林果皞's comment.
find . -type f |
file --mime-type -f - |
grep -F image/ |
rev | cut -d : -f 2- | rev
Below is a more performant solution compared to the chosen answer:
find . -type f -print0 |
xargs -0 file --mime-type |
grep -F 'image/' |
cut -d ':' -f 1
Use -type f instead of -name '*' since the former will search only files while the latter search both files and directories.
xargs execute file with arguments as many as possible, which is super fast compared to find -exec file {} \; which executes file for each found.
grep -F is faster since we only want to match fixed string.
cut is faster than awk (more than 5 times faster as I can recall).
Related to the same problem, I just published a tool called photofind (https://github.com/trimap/photofind). It behaves like the normal find-command but is specialized for image files and supports filtering of results also based on the EXIF-information stored within the image files. See the linked github-repo for more details.

How do I use find to copy and remove extensions keeping the same subdirectory structure [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'm trying to copy all the files from one directory to another, removing all file extensions at the same time.
From directory 0001:
0001/a/1.jpg
0001/b/2.txt
To directory 0002:
0002/a/1
0002/b/2
I've tried several find ... | xargs c...p with no luck.
Recursive copies are really easy to to with tar. In your case:
tar -C 0001 -cf - --transform 's/\(.\+\)\.[^.]\+$/\1/' . |
tar -C 0002 -xf -
If you haven't tar with --transform this can works:
TRG=/target/some/where
SRC=/my/source/dir
cd "$SRC"
find . -type f -name \*.\* -printf "mkdir -p '$TRG/%h' && cp '%p' '$TRG/%p'\n" |\
sed 's:/\.::;s:/./:/:' |\
xargs -I% sh -c "%"
No spaces after the \, need simple end of line, or you can join it to one line like:
find . -type f -name \*.\* -printf "mkdir -p '$TRG/%h' && cp '%p' '$TRG/%p'\n" | sed 's:/\.::;s:/./:/:' | xargs -I% sh -c "%"
Explanation:
the find will find all plain files what have extensions in you SRC (source) directory
the find's printf will prepare the needed shell commands:
command for create the needed directory tree at the TRG (target dir)
command for copying
the sed doing some cosmetic path cleaning, (like correcting /some/path/./other/dir)
the xargs will take the whole line
and execute the prepared commands with shell
But, it will be much better:
simply make an exact copy in 1st step
rename files in 2nd step
easier, cleaner and FASTER (don't need checking/creating the target subdirs)!
Here's some find + bash + install that will do the trick:
for src in `find 0001 -type f` # for all files in 0001...
do
dst=${src/#0001/0002} # match and change beginning of string
dst=${dst%.*} # strip extension
install -D $src $dst # copy to dst, creating directories as necessary
done
This will change the permission mode of all copied files to rwxr-xr-x by default, changeable with install's --mode option.
I came up with this ugly duckling:
find 0001 -type d | sed 's/^0001/0002/g' | xargs mkdir
find 0001 -type f | sed 's/^0001//g' | awk -F '.' '{printf "cp -p 0001%s 0002%s\n", $0, $1}' | sh
The first line creates the directory tree, and the second line copies the files. Problems with this are:
There is only handling for directories and regular files (no
symbolic links etc.)
If there are any periods (besides the
extension) or special characters (spaces, etc.) in the filenames
then the second command won't work.

Resources