tags:

views:

73

answers:

5

I have a list of files with numeric file names (e.g. #.php, ##.php or ###.php) that I'd like to copy/move in one fell swoop.

Does anyone know of an ls or grep combo command to accomplish this objective?

I do have this much:

ls -al | grep "[0-9].php"
+5  A: 

Amend it like this:

ls -al | grep -E '^[0-9]+\.php$'

-E activates the extended regular expressions.

+ requires that at least one occurrence of the preceding group must appear.

\. escape dot otherwise it means "any character."

^ and $ to match the entire filename and not only a part.

Single quotes to prevent variable expansion (it would complain because of the $).

UncleZeiv
Don't use `ls` in scripts, it is intended only for interactive use.
Philipp
@Philipp: Nobody mentioned scripts.
Troubadour
@Troubadour: The pipe into `grep` makes it a "script".
Dennis Williamson
@Troubadour: You're right, but I don't think that the OP asks a question like this for interactive use. Also, many people who do write scripts read these posts.
Philipp
@Philipp: Nothing about the question even hints at non-interactive use so that's a real jump. Also, you can't turn the question into a scripting question just because you think people who write scripts might be reading.
Troubadour
Edit to first comment: "Don't use `ls` in scripts or pipes, it is intended only for interactive use. See [ParsingLs](http://mywiki.wooledge.org/ParsingLs)."
Dennis Williamson
@Philipp, @Dennis: ok, ok, no more `ls` in scripts or pipes, I promise!
UncleZeiv
A: 

You can use regular expression when listing files:

ls [0-9]*

This was an easy and minimalistic approach at the above problem but I think a better solution is

ls -al | grep -E '^[0-9]+\.php$'

as UncleZeiv explains below.

ppolyzos
Surely this depends on the shell? For example `bash` wouldn't treat that as a regular expression. Try it and you'll see it matches _any_ file whose name starts with a number.
Troubadour
Actually I'm running bash and it worked perfectly. This was far too simple. Thanks for the solution. I used cp [0-9]*
gurun8
@gurun8: You were lucky you didn't have any files with non-numeric characters in their name then.
Troubadour
@gurun8 may be this worked for you, but this would fail if there are files such as 123myfile.php
ring bearer
This works only by accident and shouldn't be the accepted answer. Try it with a directory that contains a file such as `0a.txt`.
Philipp
That's globbing, not a regular expression.
Dennis Williamson
+1  A: 

Use find:

$ find . -regex '^[0-9]+\.php' -exec mv '{}' dest/ ';'

Note that the -regex argument does a search, not a match, which is why the ^ is there to anchor it to the start. This also assumes that the files are in the same directory (.) as the one you're in when running the command.

The {} trickery in the mv command is replaced by find with the found filename.

unwind
+1 for using find
zdav
but no +1 for using it this way. This will break on file names with spaces or newlines. Instead use `find . -regex '^[0-9]+\.php' -exec mv '{}' dest/ ';'`, or `xargs -0`.
Philipp
@Philipp: Thanks, that's more robust. I got the impression the original poster's set of filenames didn't contain spaces, but being safe is better of course.
unwind
@unwind: If the pattern is really just `^[0-9]+\.php$`, then of course your original code doesn't cause problems. However, I guess that lots of readers would blindly modify your code to include other patterns which then lead to problems.
Philipp
A: 

Either use find (possibly combined with the -XXXdepth options):

find . -mindepth 1 -maxdepth 1 -regex '^[0-9]+\.php' -exec mv '{}' dest/ ';'

Or use the builtin regex capabilities:

pattern='^[0-9]+\.php$'
for file in *.php
do
    [[ $file =~ $pattern ]] && echo "$file"
done

Don't use ls or grep.

Philipp
+1  A: 

In Bash, you can use extended pattern matching:

shopt -s extglob
ls -l +([0-9]).php

which will find files such as:

123.php
9.php

but not

a.php
2b.php
c3.php
Dennis Williamson