Recursive find that will append directory name to any file - linux

Any help would be greatly appreciated!
I need a way to append the parent directory name to any file in any path.
An example current directory tree
/Hawaii/Surfing/800x600/picture1.jpg
/Hawaii/Surfing/800x600/picture2.jpg
/Hawaii/Surfing/800x600/picture3.jpg
/RockClimbing/SouthAfrica/TableMountain/4096x2160/Picture1.jpg
/RockClimbing/SouthAfrica/TableMountain/4096x2160/Picture2.jpg
/RockClimbing/SouthAfrica/TableMountain/4096x2160/Picture3.jpg
The goal
/Hawaii/Surfing/800x600/picture1.800x600.jpg
/Hawaii/Surfing/800x600/picture2.800x600.jpg
/Hawaii/Surfing/800x600/picture3.800x600.jpg
/RockClimbing/SouthAfrica/TableMountain/4096x2160/Picture1.4096x2160.jpg
/RockClimbing/SouthAfrica/TableMountain/4096x2160/Picture2.4096x2160.jpg
/RockClimbing/SouthAfrica/TableMountain/4096x2160/Picture3.4096x2160.jpg
I have found some examples of this but the users all have set directory depths unfortunately I have files at many different levels.
find dir -name *.jpg -exec rename -nv -- 's|/(.*)/(.*)$|/$1/$1.jpg|' {}

Your first capture group is matching everything before the last /, not just the last directory name. Use /([^/]*)/ instead of /(.*)/ so it won't match across / delimiters. You're also not splitting up the filename into the name and extension, so you're not inserting the directory name between them.
find dir -name *.jpg -exec rename -nv -- 's|([^/]*)/([^/]*)\.jpg$|$1/$2.$1.jpg|' {} +

Related

How to remove all files except the ones that matches a pattern along several number of directories

lets say I have a my_dirs/ directory, insdie that directory I have several parallel subdirectories which has several files and I want to delete all of them except the ones that have the substring '.regions'
this is my parent directory content:
this is what I tried:
shopt -s extglob
rm -r !(./**/*.regions*)
but I got an error message: cannot be deleted «! (./**/*. region *) »: The file or directory does not exist.
how can I do that?
First of all, always be careful when deleting multiple files.
The command to achieve what you want would be:
find my_dirs -type f ! -name "*.regions*" -delete
"-delete" must be last, otherwise it will delete everything it finds
This will explore all subdirectories in my_dirs, find the files (-type f) that not (!) contain ".regions" ("*.regions*") on their name, and delete (-delete) them.
I recommend running this first: find my_dirs -type f ! -name "*.regions*",
so it won't delete anything and you can check the files are correct.
Edit: Added -type f so it only targets files per Philippe's suggestion.

linux command line subfolder files batch rename that actually works

In a folder with many subfolders, each containing mp4 files with names ending in foobar.mp4
How can I get rid of the suffix? I have tried:
find ./*/*.mp4 -type f -exec rename 's/foobar//' '{}' \;
On surface, there is no need to use 'find', as the rename command has the ability to process list of file. In particular, possible to write
rename 's/foobar//' */*foobar.mp4
It's not clear from the OP what are the actual file names. The above command will rename 'foobar.mp4' to hidden file '.mp4', and the file 'x.foobar.mp4' to 'x..mp4'.

copying all the .tar and .tar.bz2 file systems from all the sub-directories into another directory

Imagine that i have lots of sub-directory in a sub-directory in a directory I wanted to copy all the .tar and .tar.bz2 extension files from all the sub-directories into another directory.
I used
$find /home/apple/mango -name *.tar -exec cp {} ./kk \;
but it copies only once from a sub directory and stops , it doesn't find files which are in other sub directories or go inside a sub directories and find them.
I want to do it recursively
You may use:
find /home/apple/mango -name '*.tar*' -execdir cp {} /full/path/to/kk \;
Note how name pattern is quoted to avoid shell expansion even before find command executes.
In the absence of quoting *.tar is expanded to some file.tar which is present in current directory and find stop right there because file.tar is not found in sub directories. By quoting glob pattern we make sure that find command gets literal pattern to search the sub directories.

Linux backup all files with known extensions with timestamps

I want to backup all files with a given extension in a directory but I want them to be with timestamps.
Given a directory:
Sample/ with multiple subdirectory and a subfolder name BACKUPS.
cd Sample
find . -name '*.xml' -exec cp {} BACKUPS \;
Say I have multiple xml files in this Sample folder and I want them to be copied to the BACKUPS folder but I want them to be timestamp
say..
text.xml.20171107
conf.xml.20171107
I am able to backup the files but I could not figure out how to append a timestamp to the files using the find command.
You could try this:
find . -name '*.xml' -execdir cp {} "$PWD/BACKUPS/{}.$(date +%Y%m%d)" \;
As before, we use find . -name '*.xml' to locate all the files. However, in order to get rid of the names of subdirectories, we use -execdir instead of exec. This causes the specified command to be run from inside the subdirectory the current file is in and replaces {} by its base name.
This means we have to modify cp's second argument (the target filename). We now pass "$PWD/BACKUPS" to create an absolute path ($PWD is the current working directory). This way cp always targets the right directory, even when invoked from a subdirectory of Sample.
Finally, the filename we use is constructed from {}.$(date +%Y%m%d). $( ) runs the specified command and substitutes its output (the current date, in this case). This is done by the shell before find is invoked, so find just sees .../{}.20171107. The {} part is replaced by find itself just before it runs each cp.

How to get a bare, recursive directory listing in Linux, excluding some directories

I need to obtain a recursive directory listing in Linux with only the directory and file name. It needs to include all files including hidden files with the exception of files name “.svn”.
I have tried multiple combinations of the “ls” command and haven’t been able to figure it out. When using “ls –R direname/ grep –v /$” I get a directory heading followed by a colon, which I cannot use.
If I have a directory name test with files and a sub-directory named test2 with files, I need the output to look like the following:
test
test/.filehidden1
test/file2
test/file3.txt
test/test2.log
test/test2/file.hidden1
test/test2/file2.boo
test/test2/file3.boo2
Notice there is no leading forward slash
find . -name .svn -prune -o -print
-prune tells it to not descend into any matching directories.
This should do:
find . ! -path \*.svn\*
This tells find to recursively list all files from . whose pathname does not contains .svn. This is not perfect since it may hide for instance file foo.svnbar.
Something like this:
find DIRNAME ! -name .svn
I need to obtain a recursive directory listing in Linux with only the directory and file name. It needs to include all files including hidden files with the exception of files name “.svn”.
Do you want to get a list of files in a Subversion repository?
This will do just that:
svn ls -R
If not, then you can use find:
find . ! -path '*/.svn/*' ! -name .svn
You mentioned "Notice there is no leading forward slash".
If that's very important, then the find command can be rephrased as:
find * .[^.]* ! -path '.svn/*' ! -name .svn

Resources