Recursively remove portion of filename that matches a pattern - unix

I'm on a UNIX system. Within a directory (and any of its subdirectories), I'm trying to rename all files that match a certain pattern:
change hello (1).pdf
to hello.pdf
Based on the top response from this question, I wrote the following command:
find . -name '* (1)*' -exec rename -ns 's/ (1)//' {} \;
The find works on its own and the rename also works on its own, but the above command only outputs Reading filenames from STDIN and does nothing. How can I make this work?

Figured this out! For whatever reason, it only works when you use the Perl version of rename like this:
find . -name '* (1)*' -exec rename -f -s ' (1)' '' {} \;

Related

BASH: performing a regex replace on a path from find command

AIM: to find all JS|TS excluding *.spec.js files in a directory but replace the base path with ./
I have this command
find src/app/directives -name '*.[j|t]s' ! -name '*.spec.js' -exec printf "import \"%s\";\n" {} \;
which in said directory prints the marked JS files. However I want to replace the src/app with ./
I've tried playing with [[]] and this command but they don't work.
find src/app/components -name '*.[j|t]s' ! -name '*.spec.js' -exec printf "import \"%s\";\n" ${{}/src
/hi} \;
zsh: bad substitution
Given your "AIM", all you really need is:
find src/app/directives -type f -name "*.[jt]s" ! -name "*.spec.js" -printf "./%f\n"
The reason being is the '|' in your character-class isn't matching anything, but isn't hurting anything for that matter. Your second ! -name "*.spec.js" is fine. You don't need -exec and can simply use -printf "./%f\n" (where "%f" provides the filename only for the current file). You simply prepend the "./" as part of the -printf format-string.
Let me know if I misunderstood your AIM or if you have further questions.
Removing src/app/directives While Preserving Remaining Path
If you want to preserve the remainder of the path after src/app/directives (essentially just replacing it with '.'), you can use a short helper-script with the POSIX parameter expansion to trim src/app/directives from the front of the string replacing it with '.' using printf in the helper script. For example the helper could be:
#!/bin/zsh
printf ".%s" "${1#./src/app/directives}"
(note: the leading "./" being removed along with src/app/directives is prepended by find, the '.' added by the printf format-string will result in the returned filename being ./rest/of/path/to/filename)
Call the script whatever you like, helper.sh below. Make it executable chmod +x helper.sh.
The find call would then be:
find src/app/directives -type f -name "*.[jt]s" ! -name "*.spec.js" -exec path/to/helper.sh '{}' \;
Give that a go and let me know if it does what you are needing.

trouble listing directories that contain files with specific file extensions

How to I list only directories that contain certain files. I am running on a Solaris box. Example, I want to list sub-directories of directory ABC that contain files that end with .out, .dat and .log .
Thanks
Something along these lines might work out for you:
find ABC/ \( -name "*.out" -o -name "*.log" \) -print | while read f
do
echo "${f%/*}"
done | sort -u
The sort -u bit could be just uniq instead, but either should work.
Should work on bash or ksh. Probably not so much on /bin/sh - you'd have to replace the variable expansion with something like echo "${f}" | sed -e 's;/[^/]*$;;' or something else that would strip off the last component of the path. dirname "${f}" would be good for that, but I don't recall if Solaris includes that utility...

Move files according to a specific pattern in the file name

I have to copy a list of files having the following pattern in the name: "_my_file" from sub-folders into one main folder. File names appear as the following:
A_my_file.txt
B_my_file.txt
C_my_file.txt
I used the following string but it does not work:
find . -name "*_my_file*" -exec mv "{}"./dest_fld \;
Add space between "{}" and ./dest_fld:
find . -name "*_my_file*" -exec mv "{}" ./dest_fld \;
# ^
It would be better dest_fld to be outside the currently directory. Unless, dest_fld will be scaned too.

Recursively search files named string.xml for certain text

This command will search all directories and subdirectories for files containing "text"
grep -r "text" *
How do i specify to search only in files that are named 'strings.xml'?
You'll want to use find for this, since grep won't work that way recursively (as far as I know). Something like this should work:
find . -name "strings.xml" -exec grep "text" "{}" \;
The find command searches starting in the current directory (.) for a file with the name strings.xml (-name "strings.xml"), and then for each found file, execute the grep command specified. The curly braces ("{}") are a placeholder that find uses to specify the name of the file it found. More detail can be found in man find.
Also note that the -r option to grep is no longer necessary, since find works recursively.
You can use the grep command:
grep -r "text" /path/to/dir/strings.xml
grep supports an --include option whose use is to recurse in directories only searching file matching PATTERN. So, try something like below:
grep -R --include 'strings.xml' text .
I also tried using find which seems to be quite faster than grep:
find ./ -name "strings.xml" -exec grep "text" '{}' \; -print
These links speak about the same issue, might help you:
'grep -R string *.txt' even when top dir doesn't have a .txt file
http://www.linuxquestions.org/questions/linux-newbie-8/run-grep-only-on-certain-files-using-wildcard-919822/
Try below command
find . -type f | xargs grep "strings\.xml"
This will run grep "strings\.xml" on every file returned by find

Find/grep statement code filter

I need to generate a list of IFS files that contain a given string
("iim"). (IFS is the IBM System i database) I need to search directory /linoma/goanywhere/projects
recursively. I've been able to do this with a combination of the FIND
and GREP commands in QSHELL:
find /linoma/goanywhere/userdata/projects -type f -exec grep -lRF "iim"
'{}' ';'
Here's the rub: there is a subdirectory I want to ignore
(/linoma/goanywhere/userdata/projects/demo). How would I modify my
find/grep statement to exclude the demo folder?
find /linoma/goanywhere/userdata/projects -( -type f -and -not -path '/linoma/goanywhere/userdata/projects/demo/**' -) -exec grep -IRF 'iim' '{}' ';'
should work for GNU find, I believe. If your local find doesn't support that syntax, you might also brute-force remove by appending | grep -v /linoma/goanywhere/userdata/projects/demo

Resources