9

I'm trying to get my script to ls all the files in the form "$variable".*

the parameter is always a file with the extension .001 I want to find all the files with the same name but different extension, eg $file.002, file.003 etc. eg.:

first="$1"
others=${first%.001}
ls $others"*"

My problem is the file is named file[success].mpg.001 and what gets fed to ls is file[success].mpg* which gives me ls: cannot access file[success].mpg*: No such file or directory because ls needs to see:

file\[success\].mpg*

I've been trying everything, the one thing I did notice is ls fed the parameter $1 works, but not if fed $file after I've done file=$1 . So I guess how do I change the variable into a parameter?

4 Answers 4

10

You could use bash's printf command to reformat the string. Furthermore you don't need to quote *:

#!/bin/bash
first="$1"
others=$(printf %q "${first%.001}")
ls $others*

printf %q reformats the string in a format that can be used as shell input (regarding to bash's man page).

edit regarding to a comment:
The above solution does not work with white spaces in file names. For those cases (as some other answers already mentioned) it's better not to use printf but to properly quote all variables:

#!/bin/bash
first="$1"
others="${first%.001}"
ls -- "$others"*
Sign up to request clarification or add additional context in comments.

3 Comments

I'm glad that I could help you.
This works for files with brackets in the names, but not for other odd characters like spaces. For example, I tried ./findfiles1 "test [success].mpg.001", and it parsed that as two filenames and didn't find either: ls: \[success\].mpg*: No such file or directory ls: test\: No such file or directory.
@Gordon: You are right. This doesn't work with spaces/tabs. For those cases it's better to go with the solution mentioned by Philipp or Kaleb to do something like ls -- "${first%.001}"*. I will add this to my answer.
5

You should quote the variable, not the wildcard:

ls -- "$others"*

The double dash stops search for options so that this code should work even if others begins with a dash.

Note that ls is more often than not the wrong solution in scripts. Use it only if you really want to print the list, e.g. in long format:

ls -l -- "$others"*

If you want to print only the names, you don't need ls at all:

echo "$others"*

Unfortunately you cannot use -- with echo. If, however, you want an array of the file names, use

filenames=("$others"*)

And should you want to iterate over them, use

for filename in "$others"*

Comments

3

You're not too far off. My first fix is changing line 3 to the following:

ls -- "${others}".*

This will expand $others and allow the globbing to happen. It's the shells responsibility to expand the * to the list of all matching filenames. The list of filenames is then sent to ls. It sounds like in most cases ls will see something like this:

file1.001 file1.002 file1.003 ...

But, when no files are present, the shell passes the glob to ls and it will see asterisk:

file1.*

Thus, your line, ls $others"*" appends a literal asterisk which ls will see.

Unless you have a file name file1.* (with a literal asterisks), ls will fail.

Another option is to use basename:

first="$1"
others=`basename -- "$first" .001`
ls -- "${others}".*

Using basename gives you the advantage that it can remove directories, etc.

However, as others have pointed out, depending on what you're doing with the list of files, find may be better.

EDIT: The double-hyphen doesn't work on all *nix variants but tells the ls and basename commands that no other cli arguments follow. Quoting your variables may be a best practices but I prefer the simplicity of leaving them off unless the data isn't trusted. Know your data and quote appropriately.

1 Comment

Your variables are not properly quoted, which causes issues if the file names contain spaces or other "special" characters. Use ls -- "$others"* and basename -- "$first" instead.
1

Use find instead ls:

$ ls weg.*
ls: weg.*: No such file or directory
$ find . -name weg.\*
$

2 Comments

find . -name file[success].mpg* doesnt find anything.
from l0b0's answer i guess i should just use a different way than ls

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.