Solaris: Find files matching a pattern but only display the directory name - find

Like it says above. I'm trying to find a simple way to look for a pattern in a file name and display only the directory in which it is found.
For example, given a tree structure that looks like this:
./projecta
./projecta/src/code1.p
./projecta/src/code2.p
./projecta/util.p
./projectb
I would want the command "whatever *.p" to return:
./projecta/src
./projecta
Hope that makes sense. Any further info, please signify in the usual manner.
TIA
N/

To display the directories of .c files:
find . -name \*.c -exec dirname {} \; | uniq
To display the directories of .html files:
find . -name \*.html -exec dirname {} \; | uniq
If you want to use that in a script,
#/bin/bash
ext=$1
find . -name \*.${ext} -exec dirname {} \; | uniq

Related

Rename files in sub-directories using find and rename

i wish to rename files with single digit numbers by adding a "0" in front, while ignoring files with double digit numbers, for example: 1.fileA, 2.fileB to 01.fileA, 02.fileB, and ignoring files 10.fileK, 11.fileL
when i use the following command, nothing happens. i assume it's because find returns the full path of the filename for which my rename function does not work. below, mediaDir is the path to my folder where my media files are located.
i tried the following but it still does not work:
find "$mediaDir" -type f -name "*.mp4" -exec rename 's/^(\d)\./0$1./' {} \;
so i tried the following instead, which also does not rename the files:
find "$mediaDir" -type f -name "*.mp4" -exec rename 's/^(\d)\./0$1./' $(basename {}) \;
although the following correctly lists out the basename of the files without the fullpath
find "$mediaDir" -type f -name "*.mp4" -exec basename {} \;
i have spent a whole day googling and trying but to no avail. please help.
After struggling further to understand the find command, thanks to Kusalananda who did a great job explaining "find" that "man find" does an incomplete job of:
Basic usage of -exec
In my question above, -exec doesn't work because find returns the full path to the found file, which makes my rename's regex using ^ fail since the digit to be appended to is no more at the start of the string, being within the full path.
Using "-execdir" instead, returns only the filename minus the path; however, GNU find prefixes the returned filename with "./" which defeats my regex. the following finally worked:
find "$mediaDir" -type f -name "*.mp4" -execdir rename 's/\/(\d)\./\/0$1./' {} \;
Note that the "^" is no more in my regex expression, due to the "./" prefix that "find" appends
To use -exec instead of -execdir, the following worked:
find "$mediaDir" -type f -name "*.mp4" -exec basename {} \; -exec rename 's/\/(\d)\./\/0$1./' {} \;
It seems that "-execdir" is shorter and better than "-exec".
Use find with regex to match only one digit and then process the output in a loop, executing mv to rename the file.
while read file;
do
filename=${fil3##*/}; # Extract the directory
dir=${file%/*} # Extrasct the file name
mv "$file" "$dir/0$filename" # Execute the move command
done <<< "$(find /path/to/dir -regextype posix-extended -regex "^.*/[[:digit:]]{1}\.file.*")"

Find files and delete characters in the filenames

So I have a directory called testdir and I want to delete the underscores in the filenames from the files in that directory.
I tried to use this command
find testdir -type f -exec ls {} \; | sed 's/_*//'
It will output the filenames without the underscores but it won't delete the underscores permanently. Could anyone help me?
Thanks!
If you are just looping through the files in your dir, use a simple loop:
while IFS= read -r file
do
echo mv "$file" "${file//_/}" #once you are sure it works, remove the echo!
done < <(find -type f -name "*_*")
This will feed the while loop with the output of the find command. Then, uses ${var//_/} to remove all _ in the name.
Why wasn't your approach working?
Because you are saying
find ... -exec ls {} \; | sed '...'
That is, you are finding something and then changing the output with sed. That is, nothing is done to the file itself.
This may help you
find testdir -type f | rename 's/_//'
Regards

Files not available after running find command

I tried to rename files ending with ".txt" to ".abc" using the find command as below. Now the files are not available on my disk.
find ./ -type f -iname '*.txt' -exec sh -c 'mv "$0" "$1.abc"' {} \;
can someone explain me the above command in detail what is did with the files.
Is there any possibility to retrive those, if yes how ?
You used the wrong variable and most of the files cannot be retrieved.
find ./ -type f -iname '*.txt' -exec sh -c 'mv "$0" "$1.abc"' {} \;
will rename every .txt file to a file called .abc. So if you files named bar.txt and foo.txt it will rename bar.txt to .abc and then rename foo.txt to .abc which will overwrite the original contents of bar.txt. You cannot see the file because it is .abc and is hidden under a normal list. If you run 'ls -a' you will see a file named ".abc" which will have the contents of the last .txt file that was renamed.
I am not sure how to do exactly what you wanted but running
find ./ -type f -iname '*.txt' -exec sh -c 'mv "$0" "$0.abc"' {} \;
will rename each .txt file to a .txt.abc file. So you would have bar.txt.abc and foo.txt.abc
The explanation of rondo is correct.
But what are the solutions for your problem?
If you want to replace the suffix .txt with .abc you can use rename
You will have success, if you use rename and find like this:
find . -type f -iname '*.txt' -print0 | xargs -0 rename .txt .abc
For all files found by find like x.txt or a/b.txt the appropriate command will execute, e.g.
rename .txt .abc x.txt
rename .txt .abc a/b.txt
so x.txt -> x.abc, and a/b.txt -> a/b.abc
If you only want to add the suffix .abc to all files you can still use mv
find . -type f -iname '*.txt' -print0 | xargs -0 mv {} {}.abc
With xargs for each file the command mv is executed.
BTW: with the find option "-print0" and the xargs option "-0" the commands work also with filenames which includes spaces.

How to create links to all subfolders containing specified text in their names

As specified in title I am looking for a way how to create links to all subfolders containing specified text in their names, so for example for all subfolders of root directory containing ".app" in their names an link will be created to "/AppLinks" directory. I would like to use it in bash script (open source, free).
Does anyone know how to do that?
I searched it by google with no luck.
find yourdir -type d -name '*.app' -exec ln -s {} /AppLinks \;
Find all directories named something.app in yourdir, and create a symlink to them in /AppLinks.
single line bash-fu
function FUNCsymlink() { echo "$1"; fileName=`basename "$1"`; ln -s "$1" "/AppLinks/$fileName"; }; export -f FUNCsymlink; find `pwd`/ -maxdepth 1 -type d -iname "*.app" -exec bash -c "FUNCsymlink '{}'" \;
to easy reading:
function FUNCsymlink() {
echo "$1";
fileName=`basename "$1"`;
ln -s "$1" "/AppLinks/$fileName";
};
export -f FUNCsymlink;
find `pwd`/ -maxdepth 1 -type d -iname "*.app" -exec bash -c "FUNCsymlink '{}'" \;
you may have to adjust it a bit for your specific solution.
wherever you run it, it will create the symlinks to /AppLinks
it will only look for direct subfolders, not subfolders of subfolders, thats what I believe you need..

using find command to search for all files having some text pattern

I use following find command to find and show all files having the input text pattern.
find . -type f -print|xargs grep -n "pattern"
I have many project folders each of which has its own makefile named as 'Makefile'.(no file extension, just 'Makefile')
How do i use above command to search for a certain pattern only in the files named Makefile which are present in all my project folders?
-AD.
-print is not required (at least by GNU find implementation). -name argument allows to specify filename pattern. Hence the command would be:
find . -name Makefile | xargs grep pattern
If you have spaces or odd characters in your directory paths youll need to use the null-terminated method:
find . -name Makefile -print0 | xargs -0 grep pattern
find . -type f -name 'Makefile' | xargs egrep -n "pattern"
use egrep if you have very long paths
Duplicate of : this
You can avoid the use of xargs by using -exec:
find . -type f -name 'Makefile' -exec egrep -Hn "pattern" {} \;
-H on egrep to output the full path to the matching files.
grep -R "string" /path
Please find this link
http://rulariteducation.blogspot.in/2016/03/how-to-check-particluar-string-in-linux.html
you can use ff command i.e ff -p .format. For eg ff -p *.txt
Find big files occupying large disk space
we need to combine multiple command .
find . -type f | xargs du -sk | sort -n | tail;