Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find in directory that starts with dash

find interprets a dash at the start of a filename as the start of an option. Using the familiar -- trick doesn't work since options are after the filename, quoting has no effect, and replacing the first dash with \- doesn't work either. Users are often encouraged to precede such filenames with ./, but what can I do if I don't know whether the given path will be absolute or relative?

Edit: One solution is to find "$(readlink -f -- "$test_filename")", but it's ugly. Any better ideas?

Edit 2: Thanks for the suggestions. Here are the two scripts that resulted from this effort: safe-find.sh; safe-count-files.sh

like image 922
l0b0 Avatar asked Nov 26 '10 14:11

l0b0


People also ask

Can a filename start with a dash?

Sometimes you can slip and create a file whose name starts with a dash ( - ), like -output or -f. That's a perfectly legal filename.

How do I start a CD folder with dash?

The only solution is to put two dashes before passing the directory name.

What is a dashed file?

A DASH file is a video file created for high-quality video playback on sites such as YouTube and Netflix. It contains an HTTP-based segment of media content that is encoded with different bit rates, to keep a video playing through changing network conditions.

How do I delete a file from the beginning of a dash?

You can use standard UNIX or Linux rm command to delete a file name starting with - or -- . All you have to do is instruct the rm command not to follow end of command line flags by passing double dash -- option before -foo file name.


1 Answers

Here is a way that should work on all Unix-like systems, with no requirement on a specific shell or on a non-standard utility¹.

case $DIR in
  -*) DIR=./$DIR;;
esac
find "$DIR" …

If you have a list of directories in your positional parameters and want to process them, it gets a little complicated. Here's a POSIX sh solution:

i=1
while [ $i -le $# ]; do
  case $1 in
    -*) x=./$1;;
    *) x=$1;;
  esac
  set -- "$@" "$x"
  shift
  i=$(($i + 1))
done
find "$@" …

Bourne shells and other pre-POSIX sh implementations lack arithmetic and set --, so it's a little uglier.

i=1
while [ $i -le $# ]; do
  x=$1
  case $1 in
    -*) x=./$1;;
  esac
  set a "$@" "$x"
  shift
  shift
  i=`expr $i + 1`
done
find "$@" …

¹ readlink -f is available on GNU (Linux, Cygwin, etc.), NetBSD ≥4.0, OpenBSD ≥2.2, BusyBox. It is not available (unless you've installed GNU tools, and you've made sure they're in your PATH) on Mac OS X (as of 10.6.4), HP-UX (as of 11.22), Solaris (as of OpenSolaris 200906), AIX (as of 7.1).

like image 166
Gilles 'SO- stop being evil' Avatar answered Oct 14 '22 00:10

Gilles 'SO- stop being evil'