170
find . -type f -print

prints out

./file1
./file2
./file3

Any way to make it print

file1
file2
file3

?

breadjesus
  • 1,979
  • 3
  • 13
  • 8
  • 1
    if you used `-exec /path/to/myscript.sh {} ` in your `find`, the `-printf '%P\n'` does not work. Instead, I have to do the `./` prefix chomping inside the script by: `p=${1#"./"}` – daparic Oct 21 '18 at 03:50
  • If you are doing it just for a single file: ``f=`find . -name migration`; echo ${f/.\//}`` – masterxilo Jan 23 '19 at 17:48

8 Answers8

302

Find only regular files under current directory, and print them without "./" prefix:

find -type f -printf '%P\n'

From man find, description of -printf format:

%P     File's name with the name of the command line argument under which it was found removed.

7ochem
  • 2,183
  • 1
  • 34
  • 42
Ilia K.
  • 4,822
  • 2
  • 22
  • 19
  • 22
    +1 Good solution if your version of `find` supports `-printf` (not all do). – Todd Owen Jan 09 '12 at 08:58
  • 2
    As Todd said, but more precisely: it ain't POSIX 7. – Ciro Santilli OurBigBook.com Feb 16 '14 at 12:42
  • 9
    Supported or not, it's definitely safer than the accepted answer. – Dale C. Anderson Dec 11 '15 at 18:08
  • 12
    You can use `\0` instead of `\n` if you want to pipe it to `xargs -0` (eg in case filenames contain whitespace), eg `find -type f -printf '%P\0' | xargs -0 head` – seanf Jun 02 '17 at 03:05
  • 1
    @Quanlong , it works on macOS if you `brew install findutils` ;) – blockloop Jan 11 '18 at 22:53
  • to elaborate on @blockloop's comment: on OS X, install `findutils`, and use `gfind` instead of `find`. That installs GNU find. – hraban Mar 14 '18 at 23:04
  • I recommend using `brew install findutils --with-default-names` to prevent adding the `g` prefix if you prefer the GNU tools. If you exclude the flag then yes, you will need to use the `g` prefix. – blockloop Mar 15 '18 at 18:02
  • If you need to quote the file paths in a shell-safe manner, you could do `find … -printf '%P\0' | xargs -0r printf '%q\n'`. See `man printf` for what `%q` does. – Robin479 Mar 22 '18 at 17:06
  • I like `-printf '%P\n'` , but the path inside a shell script via `-exec myscript.sh {} \;` still contains the `./` thing in the path – daparic Oct 21 '18 at 03:41
  • Busybox v1.30.1 (used in the current `docker:latest` image) find also does not seem to support `-printf` – debuglevel Oct 12 '19 at 22:04
68

Use sed

find . | sed "s|^\./||"
Lie Ryan
  • 62,238
  • 13
  • 100
  • 144
  • 4
    This is my preferred solution; it is POSIX-compatible (works practically everywhere, even embedded systems), very short, and unlikely to result in unexpected behavior. This should be the accepted answer. – Jody Bruchon Nov 25 '16 at 14:39
  • 7
    How would this be combined with `find -exec`? – Paul Wintz Jan 18 '17 at 22:13
  • `find -exec sh -c "echo {} | sed 's|^\./||'" \;` or `find -exec sh -c "sed 's|^\./||' <<< '{}'" \;` – xenithorb Oct 19 '17 at 13:34
42

If they're only in the current directory

find * -type f -print

Is that what you want?

Tim Green
  • 2,028
  • 1
  • 17
  • 19
  • I knew it could be done with sed, but this is a much better solution. Thanks! – breadjesus Apr 07 '10 at 23:13
  • 27
    This will miss files with names that start with a period. – Sean Apr 07 '10 at 23:58
  • 4
    Bad, depending on a shell settings * may not evaluate to "hidden" files/directories -- those which begins with dot (.) Try to run this command in your home dir, then just "find -type f" and see the difference. – Ilia K. Apr 08 '10 at 00:01
  • While, overall, this is a good point, I don't think it applies to this context. If anything, it just makes it more useful. Nothing more annoying then listen your root and getting files like bashrc, htaccess and bash_history. – Tim Green Apr 08 '10 at 00:14
  • 44
    A more relevant concern is that '*' is evaluated by the shell. You effectively have a type of malicious code injection situation. It would be trivial to create a file named ' --exec rm ' and another named 'zzzz ;'. Goodbye files. – CWF Apr 08 '10 at 00:39
  • 1
    Fails on OSX. The answer by Ilia K. is better IMHO. – joelparkerhenderson Nov 19 '14 at 01:10
  • 7
    This is unsafe. If a file name starts with a dash, it will be treated as an option to find, and may fail, or could potentially do damage. – Dale C. Anderson Dec 11 '15 at 17:53
  • 4
    Why is `-print` required? It gave same result without that flag. – user13107 Apr 29 '16 at 03:20
  • 1
    This answer should have a disclaimer about the dangers – Ferrybig Sep 05 '19 at 07:03
  • tried to use this for folders: `find . -type d -print`, but it still prepends `./` to them – ssc Jun 04 '20 at 09:55
  • @ssc the difference is `find *` versus `find .` –  Jul 08 '20 at 10:44
9

it can be shorter

find * -type f
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
  • Better with `2> /dev/null` to ignore error reported when the command is run in an empty directory. – neevek Dec 17 '16 at 06:13
  • 5
    Unsafe, just like the accepted answer. `*` is expanded by the shell, so any filename starting with `-` will be interpreted as an option to `find`. – jbg May 02 '21 at 11:24
7

Another way of stripping the ./ is by using cut like:

find -type f | cut -c3-

Further explanation can be found here

banjoAtix
  • 151
  • 2
  • 4
4

Since -printf option is not available on OSX find here is one command that works on OSX find, just in case if someone doesn't want to install gnu find using brew etc:

find . -type f -execdir printf '%s\n' {} + 
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    Unfortunately this strips the whole path of each found file, including intermediate subdirectories, and just prints the filename itself. – PLL Jun 24 '20 at 16:42
  • 2
    You are right. This solution is only good for files in current directory. For nested files we need to use: `find . -type f -exec bash -c 'for f; do echo "${f#./}"; done' {} +` – anubhava Jun 24 '20 at 20:43
2

Another way of stripping the ./

find * -type d -maxdepth 0
Valheru
  • 37
  • 1
  • While this code may solve the question, [including an explanation](https://meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply. – David Buck Mar 18 '20 at 11:42
  • 1
    Unsafe, just like the accepted answer. `*` is expanded by the shell, so any filename starting with `-` will be interpreted as an option to `find`. – jbg May 02 '21 at 11:24
2

For files in current directory:

find . -maxdepth 1 -type f | xargs basename -a

-maxdepth 1 -> basically this means don't look in subdirectories, just current dir
-type f     -> find only regular files (including hidden ones)
basename    -> strip everything in front of actual file name (remove directory part)
-a          -> 'basename' tool with '-a' option will accept more than one file (batch mode)
Damir
  • 133
  • 4