user2171053
user2171053

Reputation:

bash find treating * as *

#!/bin/bash
read nameArg
find -name "$nameArg"

With this code when I input for example *.txt it will give me all the files that ends on txt, but I want only the specific one which name is *.txt. How to make bash treating * as * ?

Straight in terminal I know I should do:

find -name "\*.txt"

How to make it work in script ? Note there will not always be * in input.

Upvotes: 2

Views: 106

Answers (3)

Ed Morton
Ed Morton

Reputation: 203995

Unfortunately you need something like this to fully solve your problem:

nameArg="$1"
find -print0 |
xargs -0 -L 1 awk -v n="$nameArg" 'BEGIN{f=ARGV[1]; sub(/.*\//,"",f); if (f==n"") print ARGV[1]; exit}' 2>/dev/null

i.e. find all files first and then select only those whose names satisfy a string comparison against your target string.

AFAIK there is no way to tell find so search for strings rather than patterns and there is no way to reliably escape the shell globbing characters in the find search pattern.

Upvotes: 0

William
William

Reputation: 4935

You could escape the * on the fly like this:

find -name "${nameArg//\*/\\*}"

If, as Ed suggests, you might want a more general solution, you could use printf's %q format:

nameArg=$(printf '%q' "$nameArg")

or if your printf supports it:

printf -v nameArg '%q' "$nameArg"

Upvotes: 3

chepner
chepner

Reputation: 531808

You should escape the * in your input. If you write your script to escape them for you, you lose the ability to provide input that contains * as both a literal character and a metacharacter. As an example, how would you provide the pattern \*.* (name is *, with an arbitrary extension) to an auto-quoting script?

#!/bin/bash

read -r nameArg
find . -name "$nameArg"

Then on the command line:

$ bash myscript.sh
> \*.txt

Upvotes: 0

Related Questions