Find file case insensitively on unix - bash

I am working on an aix and expecting to receive a file named e.g. "afilename0729". The file is however uploaded from a Windows machine. I don't have the control of that sometimes it comes with the name "AFILENAME0729". Originally I wrote a naive
ls afilename*
to locate it within a script. But instead of writing something like
find . -name "[aA][fF][iI][lL][eE][nN][aA][mM][eE][01][0-9][0-3][0-9]"
Would there be any better way to do this?

Use '-iname' to ignore case.
e.g.
find . -iname afilename*
I also found this unix.stackexchange answer for the same question

You can use -iname or for regex support use -iregex for ignore case matching in find:
find . -iregex '.*afilename[01][0-9][0-3][0-9]'

You started with a ls (looking in the current dir only).
The simple form without checking the numbers would be
ls | grep -i "afilename*"
You can also use regular expressions with
ls | egrep -i "^afilename[01][0-9][0-3][0-9]"
When you use regex, the * is not a normal wildcard:
Looking for files starting with an "a" and ending with [0-9], do not use
ls | egrep -i "^a*[0-9]$"
but use
ls | egrep -i "^a.*[0-9]$"

If you're using GNU find, you can use the case insensitive -iname instead of -name.
From the manpage:
-iname pattern:
Like -name, but the match is case insensitive. For example, the patterns fo* and F?? match the file names Foo, FOO, foo, fOo, etc. The pattern *foo* will also match a file called .foobar.

Related

Given a text file with file names, how can I find files in subdirectories of the current directory?

I have a bunch of files with different names in different subdirectories. I created a txt file with those names but I cannot make find to work using the file. I have seen posts on problems creating the list, on not using find (do not understand the reason though). Suggestions? Is difficult for me to come up with an example because I do not know how to reproduce the directory structure.
The following are the names of the files (just in case there is a formatting problem)
AO-169
AO-170
AO-171
The best that I came up with is:
cat ExtendedList.txt | xargs -I {} find . -name {}
It obviously dies in the first directory that it finds.
I also tried
ta="AO-169 AO-170 AO-171"
find . -name $ta
but it complains find: AO-170: unknown primary or operator
If you are trying to ask "how can I find files with any of these names in subdirectories of the current directory", the answer to that would look something like
xargs printf -- '-o\0-name\0%s\0' <ExtendedList.txt |
xargs -r0 find . -false
The -false is just a cute way to let the list of actual predicates start with "... or".
If the list of names in ExtendedList.txt is large, this could fail if the second xargs decides to break it up between -o and -name.
The option -0 is not portable, but should work e.g. on Linux or wherever you have GNU xargs.
If you can guarantee that the list of strings in ExtendedList.txt does not contain any characters which are problematic to the shell (like single quotes), you could simply say
sed "s/.*/-o -name '&'/" ExtendedList.txt |
xargs -r find . -false

find/grep to list found specific file that contains specific string

I have a root directory that I need to run a find and/or grep command on to return a list of files that contain a specific string.
Here's an example of the file and directory set up. In reality, this root directory contains a lot of subdirectories that each have a lot of subdirectories and files, but this example, I hope, gets my point across.
From root, I need to go through each of the children directories, specifically into subdir/ and look through file.html for the string "example:". If a result is found, I'd like it to print out the full path to file.html, such as website_two/subdir/file.html.
I figured limiting the search to subdir/file.html will greatly increase the speed of this operation.
I'm not too knowledgeable with find and grep commands, but I have tried the following with no luck, but I honestly don't know how to troubleshoot it.
find . -name "file.html" -exec grep -HI "example:" {} \;
EDIT: I understand this may be marked as a duplicate, but I think my question is more along the lines of how can I tell the command to only search a specific file in a specific path, looping through all root-> level directories.
find ./ -type f -iname file.html -exec grep -l "example:" {} \+;
or
grep -Rl "example:" ./ | grep -iE "file.htm(l)*$" will do the trick.
Quote from GNU Grep 2.25 man page:
-R, --dereference-recursive
Read all files under each directory, recursively. Follow all symbolic links, unlike -r.
-l, --files-with-matches
Suppress normal output; instead print the name of each input file from which output would normally have
been printed. The scanning will stop on the first match.
-i, --ignore-case
Ignore case distinctions in both the PATTERN and the input files.
-E, --extended-regexp
Interpret PATTERN as an extended regular expression.

Adding prefixes to certain filenames in Unix

I need to create a script that will go through and add underscores to all files in multiple directories, ignoring the files that already have prefixes. For example, _file1, _file2, file3, file4 needs to look like _file1, _file2, _file3, _file4
I've got little to no knowledge of Unix scripting, so a simple explanation would be greatly appreciated!
You could use one liner like this:
find dir_with_files -regextype posix-extended -type f -regex '^.*\/[^_][^\/]*$' -exec rename -v 's/^(.*\/)([^_][^\/]*)$/$1_$2/' '{}' \;
where dir_with_files is upper dir where you search for your files. Then it finds files with names starting not from _, and each of them is renamed.
Before doing any changes you can use rename with params -n -v showing you what operations will take place, without actually executing them.
find dir_with_files -regextype posix-extended -type f -regex '^.*\/[^_][^\/]*$' -exec rename -v -n 's/^(.*\/)([^_][^\/]*)$/$1_$2/' '{}' \;
From the best Bash resource out there:
Create a glob which matches all of the relevant files.
Loop through all of the matching files.
Remove the underscore from the file name and save the result to a variable.
Prepend an underscore to the variable.
echo the original file name followed by the changed file name using proper quotes to check that they look sane (the quotes will not be printed by echo since they are syntax).
Use mv instead of echo to actually rename the files.
In addition:
If your mv supports -n/--no-clobber, use it to avoid the possibility of data loss in case you mess up

List files matching pattern when too many for bash globbing

I'd like to run the following:
ls /path/to/files/pattern*
and get
/path/to/files/pattern1
/path/to/files/pattern2
/path/to/files/pattern3
However, there are too many files matching the pattern in that directory, and I get
bash: /bin/ls: Argument list too long
What's a better way to do this? Maybe using the find command? I need to print out the full paths to the files.
This is where find in combination with xargs will help.
find /path/to/files -name "pattern*" -print0 | xargs -0 ls
Note from comments: xargs will help if you wish to do with the list once you have obtained it from find. If you only intend to list the files, then find should suffice. However, if you wish to copy, delete or perform any action on the list, then using xargs instead of -exec will help.

How to search for file names that contain a number at a specific location in bash

How do I ensure that there is a number after a file name in find? Conceptually:
find ./directory -name filename{number}.temp
If I enter
find ./directory -name filename'[0-9]'*.temp
it will give me file names of the form filename'[0-9]'text.temp as well.
find ./directory -regex '.*/filename[0-9][0-9]*\.temp'
Note that -regex matches on the whole path, not just the filename.
The older versions of Unix find don't do regular expressions or Kornshell style globs. You can use either "?" or "*" in your glob, but that's it. The find command on Linux and Macs do have the -regex expression.
If your find command isn't gnu compatible and doesn't have the -regex parameter, you need to pipe the output to grep:
find ./directory -name 'filename*.temp' | grep '/filename[0-9].temp$'

Resources