recursive find some 'foo' and tar - bash

Consider the following folder structure
root/dirA/the_folder
root/dirA/dir2/the_folder
root/dirB/the_folder
root/dirB/dir2/the_folder
I want to recursively find and tar the dirA/the_folder and dirB/the_folder. However when I use
find root/ -name 'the_folder' -type d | xargs tar cvf myTar.tar
It will pack all folders (containing dir2/the_folder) and I don't want that. What is the solution?

In your case, wouldn't just this be enough?
tar cfv mytar.tar root/*/the_folder/

Use the -maxdepth option of find to limit the recursion depth:
find root/ -maxdepth 2 -name 'the_folder' -type d
Try man find for lots of useful options that find offers. You will be surprised. For example, you can do away with the | xargs by using find's -exec option:
find root/ -maxdepth 2 -name 'the_folder' -type d -exec tar cvf myTar.tar {} +

Related

How to write the wc's stdout into a file?

The below command will show how many characters contains in every file in current directory.
find -name '*.*' |xargs wc -c
I want to write the standout into a file.
find -name '*.*' |xargs wc -c > /tmp/record.txt
It encounter an issue:
wc: .: Is a directory
How to write all the standard output into a file?
Why -name '*.*'? That will not find every file and will find directories. You need to use -type f, and better than piping the result to xargs is using -exec:
find . -type f -maxdepth 1 -exec wc -c {} + > /tmp/record.txt
-maxdepth 1 guarantees that the search won't dive in subdirectories.
I think you maybe meant find |xargs wc -c?
find -name '.' just returns .
Filter only files, if you want only files.
find -type f

Bash delete all folders except some

I have a directory with this structure:
main/
Antispam/res/values/
strings.xml
plurarls.xml
arrays.xml
Backup/res/values/
strings.xml
plurarls.xml
arrays.xml
etc.
Antispam and Backup have other folders inside, but I do not need those. I just want to have only the values folder with the three XML files (strings.xml, plurarls.xml and arrays.xml). How can I do that?
if you run this in the parent directory:
find . -regex '.*backup.*'
you would have something like this:
./backup
./backup/res
./backup/res/value
./backup/res/value/00.xml
./backup/res/value/02.xml
./backup/res/value/01.xml
And then you can invert the match by -not
find . -not -regex '.*backup.*'
and of course you can make it more specific with -type d and literal ./
find . -type d -not -regex './backup.*'
and then do any thing you like with the output
This is what I would do. Basically just find folders excluding the parent folders and send them to oblivion.
find main/Antispam/res/values/ '!' -path main/Antispam/res/values/ -type d | xargs rm -f -r $1
find main/Backup/res/values '!' -path main/Backup/res/values -type d | xargs rm -f -r $1
Hope it works for you! :)
This work for me:
ale8530#vmi81507:~/Scrivania/APK-Tools-Linux-master/working$ find . -regex '.*res/values/strings.*'
./WaliLive/res/values/strings.xml ./SystemAdSolution/res/values/strings.xml ./SampleExtAuthService/res/values/strings.xml ./DocumentsUI/res/values/strings.xml ./CaptivePortalLogin/res/values/strings.xml ./SoundRecorder/res/values/strings.xml ./ExternalStorageProvider/res/values/strings.xml ./MiuiCompass/res/values/strings.xml ./CloudBackup/res/values/strings.xml ./BackupRestoreConfirmation/res/values/strings.xml ./AntHalService/res/values/strings.xml ./MiuiSuperMarket/res/values/strings.xml ./DownloadProvider/res/values/strings.xml ./VpnDialogs/res/values/strings.xml ./XiaomiAccount/res/values/strings.xml ./SpacesCore/res/values/strings.xml ./CdmaCallOptions/res/values/strings.xml
Can you copy this output to another director
y? Keeping the same output?
For example
From-->./WaliLive/res/values/strings.xml to ./WaliLive.apk/res/values/strings.xml
Thanks
PLEASE BACKUP YOU DATA BEFORE YOU TRY!!!
if you don't care about empty dirs (or you don't care to do everything with one command), i'll do something like:
find ! -name strings.xml ! -name plurarls.xml ! -name arrays.xml -type f -delete
if you care about empty dirs:
find -type d -print0 | xargs -0 rmdir -p

Bash script for removing specific file from certain subdirectories

On a unix server, I'm trying to figure out how to remove a file, say "example.xls", from any subdirectories that start with v0 ("v0*").
I have tried something like:
find . -name "v0*" -type d -exec find . -name "example.xls" -type f
-exec rm {} \;
But i get errors. I have a solution but it works too well, i.e. it will delete the file in any subdirectory, regardless of it's name:
find . -type f -name "example.xls" -exec rm -f {} \;
Any ideas?
You will probably have to do it in two steps -- i.e. first find the directories, and then the files -- you can use xargs to make it in a single line, like
find . -name "v0*" -type d | \
xargs -l -I[] \
find [] -name "example.xls" -type f -exec rm {} \;
what it does, is first generating a list of viable directory name, and let xargs call the second find with the names locating the file name within that directory
Try:
find -path '*/v0*/example.xls' -delete
This matches only files named example.xls which, somewhere in its path, has a parent directory name that starts with v0.
Note that since find offers -delete as an action, it is not necessary to invoke the external executable rm.
Example
Consider this directory structure:
$ find .
.
./a
./a/example.xls
./a/v0
./a/v0/b
./a/v0/b/example.xls
./a/v0/example.xls
We can identify files example.xls who have one of their parent directories named v0*:
$ find -path '*/v0*/example.xls'
./a/v0/b/example.xls
./a/v0/example.xls
To delete those files:
find -path '*/v0*/example.xls' -delete
Alternative: find only those files directly under directory v0*
find -regex '.*/v0[^/]*/example.xls'
Using the above directory structure, this approach returns one file:
$ find -regex '.*/v0[^/]*/example.xls'
./a/v0/example.xls
To delete such files:
find -regex '.*/v0[^/]*/example.xls' -delete
Compatibility
Although my tests were performed with GNU find, both -regex and -path are required by POSIX and also supported by OSX.

Delete directories with specific files in Bash Script

I would like to delete specific files if existed but also the directories that contain these files. I do know the files I would like to wipe but not the directories. So far, as I'm new in bash scripting, I think of this :
find ./ -type f -name '*.r*' -print0 | xargs -0 rm -rf &> log_del.txt
find ./ -type f -name '*.c*' -print0 | xargs -0 rm -rf &>> log_del.txt
At the moment, all files named with the specific extensions *.r* and *.c* are deleted.
But the directories are still remaining and also the subdirectories in it, if existed.
I also thought of the option -o in find to delete in one line :
find ./ -type f \( -name '*.r*' -o -name '*.c*' \) -print0 | xargs -0 rm -rf &> log_del.txt
How can I do this?
And I also see that my log_del.txt file is empty... :-(
It looks like what you really want is to remove all empty directories, recursively.
find . -type d -delete
-delete processes the directories in child-first order, so that a/b is deleted before a. If a given directory is not empty, find will just display an error and continue.
If the directories remain empty, let rmdir try to remove all of them. It will fail on any directories which have still files.
find ./ -type d -exec rmdir --ignore-fail-on-non-empty {} 2>/dev/null \;
See if this serves your requirement:
find ./ -type f -name '*.r*' -delete -printf "%h\0" | xargs -0 rmdir
If the directory contained any other files, rmdir will fail.
So consider below sample file structure:
$ find a
a/
a/a/
a/a/4
a/b/
a/b/5
a/b/4
a/b/3
a/b/2
a/b/1
$ find a -type f -name '4' -delete -printf "%h\0" | xargs -0 -r rmdir
rmdir: failed to remove ‘a/b’: Directory not empty
$ find a
a
a/b
a/b/5
a/b/3
a/b/2
a/b/1
If in above example, you want to delete directory b also, you can simply use:
$ find ./ -type f -name '*.r*' -printf "%h\0" | xargs -0 rm -rf
EDIT: As per the comment, you (OP) wanted that the empty directory tree should also be deleted. These 2 commands should help you then:
$ find ./ -type f -name '*.r*' -delete # Delete matching files
$ find ./ -empty -type d -delete # Delete tree of empty directories

Find directories not containing a specific directory

Been searching around for a bit and cannot find a solution for this one. I guess I'm looking for a leaf-directory by name. In this example I'd like to get a list of directories call 'modules' that do NOT have a subdirectory called module.
modules/package1/modules/spackage1
modules/package1/modules/spackage2
modules/package1/modules/spackage3/modules
modules/package1/modules/spackage3/modules/spackage1
modules/package2/modules/
The list I desire would contain
modules/package1/modules/spackage3/modules/
modules/package2/modules/
All the directories named module that do not have a subdirectory called module
I started with trying something this with no luck
find . -name modules \! -exec sh -c 'find -name modules' \;
-exec works on exit code, okay lets pass the count as exit code
find . -name modules -exec sh -c 'exit $(find {} -name modules|grep -n ""|tail -n1|cut -d: -f1)' \;
This should take the count of each subdirectory called modules and exit with it. No such love.
This assumes GNU find. Find all leaf directories that include only one occurrence of "modules":
find -regex '.*/modules\(/.*\|$\)' \! -regex '.*/modules/.*/modules\(/.*\|$\)' -type d -links 2
find . -name modules |\
awk '{gooddir[$1]=1}\
END {\
for(i in gooddir){\
for(j in gooddir){\
if(i!=j&&substr(i,0,length(j))==i)\
{gooddir[i]=0;break}\
}\
}\
for(i in gooddir){if(gooddir[i]==1){print i}}}'
try this?
Your start
find . -name modules \! -exec sh -c 'find -name modules' \;
wasn't bad, it just needs some improvements.
find . -name modules \! -exec sh -c 'find {} -mindepth 1 -name modules|read' \; -print
{} to search in the found modules directory, not in the top directory again
-mindepth 1 to search only under the found modules directory, not to find itself again
|read to set the exit status (unfortunately, find doesn't do it) if no files are found
-print to print the found directories

Resources