Is there any way in which i can goto a directory found out using "find" command? - linux

I would like to use a command that change the current working directory to the one i find out using the "find" command.Is there any way that I can do that on a single line in bash?
I would like to use a command that change the current working directory to the one i find out using the find command.Is there any way that I can do that on a single line in bash?
I want to go to a directory called "mydir".I only know that it is somewhere in "documents". I want to change my current working directory to "mydir".
I know that I can know the path using find -name mydir.

this should do..
$ cd "$(find . -type d -name myDir -print -quit)"
-quit to ensure at most one value is returned (and finish looking after first match), may not be supported in all finds. Otherwise you need to filter the result but will take longer.

Related

Find -perm finds file (or something else) that dosent exist

Hello i am new in the world of linux and i have a simple question:
I created a directory named testfiles and 10 textfiles inside of it with various permissions.
I tried using find -perm -u=wr | wc -l in order to count all files with rw prem for user but it counts 1 more file than it is supposed to have. I then used find -perm -u=wr to see the list and realized there is an extra line in the beginning which i am not sure what it is can someone help? How do I get rid of that?
The '.' and '..' are references to the current directory and the parent directory respectively. These exist in all linux directories. As these are treated as directories, you can ignore them by using the '-type' option of the find command, where 'f' specifies files only.
find -perm -u=wr -type f | wc -l
Note that the find command as you have it will recursively find files if another directory exists where you are running the command. You can limit it to the current directory only by using the max depth option. Run 'man find' in the terminal to see all the other options you have with the find command.

Using Perl how can I clean up left over directories with no files?

There is a specific directory which is used as a temp/scratch directory by some program.
E.g. /a/b/c/work
Under work multiple hierarchical directories may exist e.g.
/a/b/c/work/
\d1/
\d1.1
\d2
\d2.2
What I want is to clean up this work directory as there are left over files that take space.
Essentially I need to delete all subdirectories under work that the leaf directory is empty.
So if d1.1 is empty but d2.2 has files then delete everything under d1 (including d1) but not d2.
What is the cleanest/standard way to do this in perl?
I thought to use a solution with backticks e.g. rm -rf etc but I thought there could be some better way than coding sequences of ls folowed by rm
Note: Just to be clear. I want a solution in Perl as this is not a one time thing and I dont want to do this manually each time
If you use find command this way you can achieve it.
find /path/to/dir -empty -type d -delete
Where,
-empty Only find empty files and make sure it is a regular file or a directory.
-type d Only match directories.
-delete Delete files.
Always put -delete option at the end of find command as find command line is evaluated as an expression, so putting -delete first will make find try to delete everything below the starting points you specified.
To automate this in shell script follow below code:
path=`pwd`
find $path -empty -type d -delete
or you can give certain input as arguments of shell script like myShell.sh /path/to/mydir in that case the following code will be do the work,
$path=$1
find $path -empty -type d -delete
As for if you really want to go for perl you can find your answer as follows
use strict;
use warnings;
use File::Util;
my $path = '...';
my $fu = File::Util->new();
my #all_dirs = $fu->list_dir($path, '--recurse', '--dirs-only');
my #empty_dirs = grep { not $fu->list_dir($_) } #all_dirs;
also a short method
perl -MFile::Find -e"finddepth(sub{rmdir},'.')"
which is explained very good here.

parsing ls -R output into a variable in Unix

I am executing a ls-R /files/
I got the following output
./: nvision
./nvision: layout
./nvision/layout: abcd.txt
I am looking to get path in the listing like
/nvision
/nvision/layout/
/nvision/layout/abcd.txt
and I should be able to copy the required path to a variable
ps: I am not searching for nvision
I am trying to get the list of folders and files under files folder
can any one help me with that
Have you tried using find (see reference)
It would be as easy as find . to get the list of files and folders inside the current directory. Change the . to any path to obtain the list of files and directories inside that path:
nvision
nvision/abcd.txt
nvision/layout
To save it to a variable
var=`find .`
And to add the initial slash to every line (if required)
var=`find . -exec echo /{} \;`
Here var has no special meaning, it's just the variable name.
To later use the variable you can use $var or ${var}. For example, to print it or save it to file:
# Print the variable content
echo $var
# Save the content of var to a file
echo $var > /tmp/file.txt
You should really use find for these kind of things. Simply use find directory. If you require more specific output formatting you can make use of find's -printf option. Find is a really powerful tool that also allows all kinds of filtering. Make sure you check the documentation for more information: GNU FindUtils.
To store the results in a variable use one of the following statements:
result=`find ...`
or
result=$(find ...)
You can also use find to directly execute a command for each match using find's -exec option. Again, make sure to check out the documentation. It's really comprehensive.
Update (Mac / UNIX users – Linux users are not affected)
BSD find requires a path. Use
find .
instead of just
find
if you require a listing of all files in your working directory.
well the answer is all over this page you should be using find which lists all files found yo can define
where . is current folder otherwise replace . with path you are wishing to search
find .-type d -print
which lists directories only or find
or
find . -type f -print
which will list all files only
if you are looking for both then
find . -print
and if you only wish to define recursive level try
find . -maxdepth 1 -print
and here is a script
#!/bin/bash
for names in $(find . -type f -print); do
echo $names
done

Problem using 'find' in BASH

I'm following this guide to get some basic skills in Linux.
At the exercises of chapter 3 section, there are two exercises:
*Change to your home directory. Create a new directory and copy all
the files of the /etc directory into it. Make sure that you also copy
the files and directories which are in the subdirectories of /etc!
(recursive copy)
*Change into the new directory and make a directory for files starting
with an upper case character and one for files starting with a lower
case character. Move all the files to the appropriate directories. Use
as few commands as possible.
The first part was simple but I have encountered problems in the second part (although I thought it should be simple as well).
I did the first part successfully - that is, I have a copy of the /etc folder in ~/newetc - with all the files copied recursively into subdirectories.
I've created ~/newetc/upper and ~/newetc/lower directories.
My intention was to do something like mv 'find ... ' ./upper for example.
But first I thought I should make sure that I can find all the files with Upper/Lower case seperately. At this I failed.
I thought that find ~/newetc [A-Z].* (also tried: find ~/newetc -name [A-Z].*) to find all the upper case files - but it simply returns no results.
What's even stranger: find ~/newetc -name [a-z].*) returns only two files, although of course there are a lot more then that...
any idea what am I doing wrong?
Thank you for your time!
Edit: (I have tried to read the Man for find command btw, but didn't come up with anything)
The -name argument does not take a full regular expression by default. So [A-Z].* will match only if the second character is a dot.
Use the expression [A-Z]*, or use -regex and -regextype to match using a real regex.
You need to use quotes
find ~/new_etc -name "[A-Z]*"
find ~/new_etc -name "[a-z]*"
If you want to use regexp, then you must use -regex (or -iregex).
For finding stuff, the other answers tell you how to do it.
For moving the results of find, use the -exec flag (while being in newetc):
find -name "[A-Z]*" -exec mv {} upper/{} \;
find -name "[a-z]*" -exec mv {} lower/{} \;
The -name parameter takes a glob, not a regular expression (those are both very useful pages). So the dot does not have a special meaning for this parameter - It is interpreted as a literal dot character. Also, in a regular expression the * means "0 or more of the previous expression" while in a glob it means "any number of any character." So, as others have pointed out, the following should get you any files below the current directory which start with an uppercase character:
find . -name '[A-Z]*'
If you want to find all the name beginning with a capital letter you have to use
find . -name "[A-Z]*"
NOT
find [A-Z].*
otherwise yo will try to locate all the file that begin with a capital letter and have a . just after

How do I write a bash script to replace words in files and then rename files?

I have a folder structure, as shown below:
I need to create a bash script that does 4 things:
It searches all the files in the generic directory and finds the string 'generic' and makes it into 'something'
As above, but changes "GENERIC" to "SOMETHING"
As above, but changes "Generic" to "Something"
Renames any filename that has "generic" in it with "something"
Right now I am doing this process manually by using the search and replace in net beans. I dont know much about bash scripting, but i'm sure this can be done. I'm thinking of something that I would run and it would take "Something" as the input.
Where would I start? what functions should I use? overall guidance would be great. thanks.
I am using Ubuntu 10.5 desktop edition.
Editing
The substitution part is a sed script - call it mapname:
sed -i.bak \
-e 's/generic/something/g' \
-e 's/GENERIC/SOMETHING/g' \
-e 's/Generic/Something/g "$#"
Note that this will change words in comments and strings too, and it will change 'generic' as part of a word rather than just the whole word. If you want just the word, then you use end-word markers around the terms: 's/\<generic\>/something/g'. The -i.bak creates backups.
You apply that with:
find . -type f -exec mapname {} +
That creates a command with a list of files and executes it. Clearly, you can, if you prefer, avoid the intermediate mapname shell/sed script (by writing the sed script in place of the word mapname in the find command). Personally, I prefer to debug things separately.
Renaming
The renaming of the files is best done with the rename command - of which there are two variants, so you'll need to read your manual. Use one of these two:
find . -name '*generic*' -depth -exec rename generic something {} +
find . -name '*generic*' -depth -exec rename s/generic/something/g {} +
(Thanks to Stephen P for pointing out that I was using a more powerful Perl-based variant of rename with full Perl regexp capacity, and to Zack and Jefromi for pointing out that the Perl one is found in the real world* too.)
Notes:
This renames directories.
It is probably worth keeping the -depth in there so that the contents of the directories are renamed before the directories; you could otherwise get messages because you rename the directory and then can't locate the files in it (because find gave you the old name to work with).
The more basic rename will move ./generic/do_generic.java to ./something/do_generic.java only. You'd need to run the command more than once to get every component of every file name changed.
* The version of rename that I use is adapted from code in the 1st Edition of the Camel book.
Steps 1-3 can be done like this:
find .../path/to/generic -type f -print0 |
xargs -0 perl -pi~ -e \
's/\bgeneric\b/something/g;
s/\bGENERIC\b/SOMETHING/g;
s/\bGeneric\b/Something/g;'
I don't understand exactly what you want to happen in step 4 so I can't help with that part.

Resources