I'm looking for help with a one-liner that I can run from the Mac OS X terminal. I use MAMP for web development on my Mac. I have a lot of CakePHP projects in my "/Applications/MAMP/htdocs" directory. For the sake of simplicity, let's just say that I had two CakePHP projects and that this was the output of the find /Applications/MAMP/htdocs -type d -iname Controller* command:
/Applications/MAMP/htdocs/my_cake1.3_project/app/controllers
/Applications/MAMP/htdocs/my_cake1.3_project/app/tests/cases/controllers
/Applications/MAMP/htdocs/my_cake1.3_project/cake/console/templates/skel/controllers
/Applications/MAMP/htdocs/my_cake1.3_project/cake/console/templates/skel/tests/cases/controllers
/Applications/MAMP/htdocs/my_cake1.3_project/cake/libs/controller
/Applications/MAMP/htdocs/my_cake1.3_project/cake/tests/cases/libs/controller
/Applications/MAMP/htdocs/my_cake1.3_project/cake/tests/test_app/controllers
/Applications/MAMP/htdocs/my_cake1.3_project/cake/tests/test_app/plugins/test_plugin/controllers
/Applications/MAMP/htdocs/my_cake2_project/app/Controller
/Applications/MAMP/htdocs/my_cake2_project/app/Test/Case/Controller
/Applications/MAMP/htdocs/my_cake2_project/lib/Cake/Console/Templates/skel/Controller
/Applications/MAMP/htdocs/my_cake2_project/lib/Cake/Console/Templates/skel/Test/Case/Controller
/Applications/MAMP/htdocs/my_cake2_project/lib/Cake/Controller
/Applications/MAMP/htdocs/my_cake2_project/lib/Cake/Test/Case/Controller
/Applications/MAMP/htdocs/my_cake2_project/lib/Cake/Test/test_app/Controller
/Applications/MAMP/htdocs/my_cake2_project/lib/Cake/Test/test_app/Plugin/TestPlugin/Controller
Now, sometimes I want to find a piece of code that I know I used in one of my CakePHP projects' controllers, but I can't remember which project it was, so I want to search all of them. I don't want to waste time searching in the "app/tests/cases/controllers" folder or any of the ones within "cake/", though. The find /Applications/MAMP/htdocs -type d -iname Controller* | grep -i /app/Controller command gives me the list of folders I want to search in:
/Applications/MAMP/htdocs/my_cake1.3_project/app/controllers
/Applications/MAMP/htdocs/my_cake2_project/app/Controller
I just need to find a way to take that output, add a slash and asterisk (/*) to the end of each line, and pipe each line to the grep -il "string to search for" command. Any help would be appreciated. Thanks!
solution 1
maybe you want to check two options of find command: (i)path and regex
with them you could narrow your find result and pass found files to your grep -il "searchString" for example by |xargs . it looks like:
find /Applications/MAMP/htdocs -type f -ipath "*/app/Controller/*.php"
| xargs grep -il 'foo'
with -regex would be more flexiable.
solution 2
however if you really really want to :
find a way to take that output, add a slash and asterisk (/*) to the
end of each line, and pipe each line to the grep -il "string to search
for" command.
(btw, here "pipe" won't work.)
you could do this:
find .(your original find).. |grep -i "/app/Controller"
|sed -r 's#^(.*)$#grep -il "foo" \1/*#g'|sh
the trick was done by the sed....|sh. the sed line will pick the result of your previous grep, add grep command and options :(grep -il "foo") and append "/*" in order to construct a complete grep command. finally pipe to sh, to execute it.
Have you tried this?
find /Applications/MAMP/htdocs -type d -iname Controller*
-exec grep -il "string to search for" {} /;
Related
I found a little one-liner of perl code that will change the serial in my zone-files on my Bind server.
However it wont change the actual file, it just gives me the output directly to the shell.
This is what I run:
find . -type f -print0 | xargs -0 perl -e "while(<>){ s/\d+(\s*;\s*[sS]erial)/2015050466\1/; print; }"
This gives me the correct output to the shell and if I remove the print; at the end of the perl line nothing happens and I want it to actually change the files to the output I got.
I'm a total noob when it comes to Perl so this might be a simple fix so any answer would be appreciated.
I am assuming you want to replace the string inside the files found by find.
Command example below will change in-place (-i) any "foo" with "bar" for all *.txt files from curent directory.
find . -type f -name '*.txt' -print0 | xargs -0 perl -p -i -e 's/foo/bar/g;'
And for your question, you should be able to get it with this command:
find . -type f -print0 | xargs -0 perl -p -i -e 's/\d+(\s*;\s*[sS]erial)/2015050466\1/;'
Note: It is good habit to always use single quotes rather than double quotes. This is because inside double quotes, a \, $, etc. may be processed by the shell before passed to Perl. See Bash manual.
I have a file named "performance". I need to know which scripts use this file.
I don't believe there is a straight forward way of listing files used by scripts. You will have to run grep in combination of find to check if the script contains the name of the file that you want to check for. Knowing the exact name of the file will help. Using words like performance might end up grepping files that uses that word in comments.
find /path/ \( -name "*.sh" -o -name "*.pl" \) -type f -print0 | xargs -0 grep "performance"
If you're on linux, then you may install and configure auditd to watch for accesses to a particular file.
You can use the -r option to recursively grep through all sub-directories and find text. The syntax is as follows:
grep -r "performance" /dir/
I'm trying to create a symbolic link (soft link) from the results of a find command. I'm using sed to remove the ./ that precedes the file name. I'm doing this so I can paste the file name to the end of the path where the link will be saved. I'm working on this with Ubuntu Server 8.04.
I learned from this post, which is kind of the solution to my problem but not quite-
How do I selectively create symbolic links to specific files in another directory in LINUX?
The resulting file name didn't work, though, so I started trying to learn awk and then decided on sed.
I'm using a one-line loop to accomplish this. The problem is that the structure of the loop is separating the filename, creating a link for each word in the filename. There are quite a few files and I would like to automate the process with each link taking the filename of the file it's linked to.
I'm comfortable with basic bash commands but I'm far from being a command line expert. I started this with ls and awk and moved to find and sed. My sed syntax could probably be better but I've learned this in two days and I'm kind of stuck now.
for t in find -type f -name "*txt*" | sed -e 's/.//' -e 's$/$$'; do echo ln -s $t ../folder2/$t; done
Any help or tips would be greatly appreciated. Thanks.
Easier:
Go to the folder where you want to have the files in and do:
find /path/with/files -type f -name "*txt*" -exec ln -s {} . ';'
Execute your for loop like this:
(IFS=$'\n'; for t in `find -type f -name "*txt*" | sed 's|.*/||'`; do ln -s $t ../folder2/$t; done)
By setting the IFS to only a newline, you should be able to read the entire filename without getting splitted at space.
The brackets are to make sure the loop is executed in a sub-shell and the IFS of the current shell does not get changed.
I'm trying to change the name of "my-silly-home-page-name.html" to "index.html" in all documents within a given master directory and subdirs.
I saw this: Shell script - search and replace text in multiple files using a list of strings.
And this: How to change all occurrences of a word in all files in a directory
I have tried this:
grep -r "my-silly-home-page-name.html" .
This finds the lines on which the text exists, but now I would like to substitute 'my-silly-home-page-name' for 'index'.
How would I do this with sed or perl?
Or do I even need sed/perl?
Something like:
grep -r "my-silly-home-page-name.html" . | sed 's/$1/'index'/g'
?
Also; I am trying this with perl, and I try the following:
perl -i -p -e 's/my-silly-home-page-name\.html/index\.html/g' *
This works, but I get an error when perl encounters directories, saying "Can't do inplace edit: SOMEDIR-NAME is not a regular file, <> line N"
Thanks,
jml
find . -type f -exec \
perl -i -pe's/my-silly-home-page-name(?=\.html)/index/g' {} +
Or if your find doesn't support -exec +,
find . -type f -print0 | xargs -0 \
perl -i -pe's/my-silly-home-page-name(?=\.html)/index/g'
Both pass to Perl as arguments as many names at a time as possible. Both work with any file name, including those that contains newlines.
If you are on Windows and you are using a Windows build of Perl (as opposed to a cygwin build), -i won't work unless you also do a backup of the original. Change -i to -i.bak. You can then go and delete the backups using
find . -type f -name '*.bak' -delete
This should do the job:
find . -type f -print0 | xargs -0 sed -e 's/my-silly-home-page-name\.html/index\.html/g' -i
Basically it gathers recursively all the files from the given directory (. in the example) with find and runs sed with the same substitution command as in the perl command in the question through xargs.
Regarding the question about sed vs. perl, I'd say that you should use the one you're more comfortable with since I don't expect huge differences (the substitution command is the same one after all).
There are probably better ways to do this but you can use:
find . -name oldname.html |perl -e 'map { s/[\r\n]//g; $old = $_; s/oldname.txt$/newname.html/; rename $old,$_ } <>';
Fyi, grep searches for a pattern; find searches for files.
I am interested into getting into bash scripting and would like to know how you can traverse a unix directory and log the path to the file you are currently looking at if it matches a regex criteria.
It would go like this:
Traverse a large unix directory path file/folder structure.
If the current file's contents contained a string that matched one or more regex expressions,
Then append the file's full path to a results text file.
Bash or Perl scripts are fine, although I would prefer how you would do this using a bash script with grep, awk, etc commands.
find . -type f -print0 | xargs -0 grep -l -E 'some_regexp' > /tmp/list.of.files
Important parts:
-type f makes the find list only files
-print0 prints the files separated not by \n but by \0 - it is here to make sure it will work in case you have files with spaces in their names
xargs -0 - splits input on \0, and passes each element as argument to the command you provided (grep in this example)
The cool thing with using xargs is, that if your directory contains really a lot of files, you can speed up the process by paralleling it:
find . -type f -print0 | xargs -0 -P 5 -L 100 grep -l -E 'some_regexp' > /tmp/list.of.files
This will run the grep command in 5 separate copies, each scanning another set of up to 100 files
use find and grep
find . -exec grep -l -e 'myregex' {} \; >> outfile.txt
-l on the grep gets just the file name
-e on the grep specifies a regex
{} places each file found by the find command on the end of the grep command
>> outfile.txt appends to the text file
grep -l -R <regex> <location> should do the job.
If you wanted to do this from within Perl, you can take the find commands that people suggested and turn them into a Perl script with find2perl:
If you have:
$ find ...
make that
$ find2perl ...
That outputs a Perl program that does the same thing. From there, if you need to do something that easy in Perl but hard in shell, you just extend the Perl program.
find /path -type f -name "*.txt" | awk '
{
while((getline line<$0)>0){
if(line ~ /pattern/){
print $0":"line
#do some other things here
}
}
}'
similar thread
find /path -type f -name "outfile.txt" | awk '
{
while((getline line<$0)>0){
if(line ~ /pattern/){
print $0":"line
}
}
}'