96

How can I run "git status" and just get the filenames as opposed to the long relative path?

TylerH
  • 20,799
  • 66
  • 75
  • 101
Mahdi Yusuf
  • 19,931
  • 26
  • 72
  • 101

10 Answers10

115

The output of git status --porcelain, designed to be easy to parse in a script, outputs the full paths rather than relative paths regardless of where your current directory is within the tree.

Each line output by git status --porcelain has two leading characters indicating the status of the file (e.g. whether it's untracked, modified, new, deleted, etc.) followed by a space, so if you just want the full paths of everything that would be mentioned in the output of git status you can do:

git status --porcelain | sed s/^...//
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
  • 12
    Same as git status -s but without coloring. – earlonrails Feb 06 '13 at 18:51
  • 1
    I found I was looking for a slightly different question, but this still includes the status marker (which I don't believe there is an option to remove). @sehe's answer is better if you purely want the filename and nothing else. – Isaac Aggrey Aug 07 '13 at 22:05
  • 1
    @IsaacAggrey: except that with sehe's answer you have to run multiple commands, and even those commands will miss untracked files that would appear in the output of git status, so it's not an accurate answer to the question. It's easy to strip off the status characters from the start of the output produced by what I suggested - I've edited my answer to show how. – Mark Longair Aug 23 '13 at 08:59
  • 1
    @earlonrails its only the same if you're at the root, run the same commands from a subdirectory of the repo and you'll see one uses relative paths to the working directory, the other full paths in the repo's root – jxramos Mar 28 '18 at 23:55
  • 2
    @jxramos You can still use cut just change the flag for git status command, `git status --porcelain | cut -c4-`. IMO `cut` is better than using `sed` because more systems will have `cut` already installed. – earlonrails Apr 02 '18 at 18:41
  • 1
    Does not produce pathnames relative to current directory like [`git status | cut` answer](https://stackoverflow.com/a/14736749/4035845) – anthumchris Mar 14 '19 at 21:18
86

I think cut is good for this.

git status -s | cut -c4-
Asclepius
  • 57,944
  • 17
  • 167
  • 143
earlonrails
  • 4,966
  • 3
  • 32
  • 47
  • 2
    and here I was using sed to strip the status codes. never used the -c flag for cut before. nice! add this to your .gitconfig for a good daystarter: `de=!$EDITOR $( git status --porcelain | cut -c4- ) & # open all changed files in EDITOR` – John Hart Aug 02 '13 at 22:09
  • 16
    For someone who are not familiar with `cut` command, `cut -c 4-` means, take characters from fourth character. – Sanghyun Lee Feb 20 '14 at 07:15
  • 1
    Yes, cleaner than sed in this case. – Simon Pickup Apr 12 '19 at 07:48
56

Aha, I think I just understood the question: you want basenames? Tack on | while read a; do basename "$a"; done to any of the following:

how about

  • git diff --name-only

    for changes relative to index

  • git diff --name-only --staged

    for ... well staged chages :)

  • git diff --name-only HEAD

    got both

sehe
  • 374,641
  • 47
  • 450
  • 633
  • I see, if you want just _basenames_ tack this on at the end of any: ` | while read fname; do basename "$fname"; done` – sehe Mar 16 '11 at 14:27
  • 1
    Does not produce pathnames relative to current directory like [git status | cut answer](https://stackoverflow.com/a/14736749/4035845) – anthumchris Mar 14 '19 at 21:13
  • Even though it certainly only outputs relative to the root of the git repository, this is a much more to the point solution than `git status --porcelain`, since you don't need to process/clean up its output. – Miguel Ruiz Nov 03 '21 at 17:34
  • Works just great: `vi \`git dno\`` I believe the dno shortcut for git diff came in my gitconfig by default. – k00ka Feb 09 '22 at 17:43
18

A much simpler solution that is built-in to git using ls-files.

From the docs:

OPTIONS

-c --cached Show cached files in the output (default)

-d --deleted Show deleted files in the output

-m --modified Show modified files in the output

-o --others Show other (i.e. untracked) files in the output

-i --ignored Show only ignored files in the output. When showing files in the index, print only those matched by an exclude pattern. When showing "other" files, show only those matched by an exclude pattern. Standard ignore rules are not automatically activated, therefore at least one of the --exclude* options is required.

-s --stage Show staged contents' mode bits, object name and stage number in the output.

-u --unmerged Show unmerged files in the output (forces --stage)

Example showing flags can be combined as well:

git ls-files -dmo
Peter Benjamin
  • 360
  • 3
  • 11
  • Very nice. I used `git ls-files -m | grep pom.xml` after running `mvn org.codehaus.mojo:versions-maven-plugin:2.7:set` in my jenkins job. That way i don't have to know what all modules are in the project and worry about missing adding/committing them. – ranma2913 Jul 13 '22 at 15:24
3

Get the name of modified files

git status --porcelain|awk '{if($1=="M") {print "basename " $2}}'|sh

I use similar script to copy my modified files to a remote server, as below:

git status --porcelain|awk '{if($1=="M") {print "scp " $2 " account_name@server_ip:~/my_codebase/$(dirname " $2 ")/;"} }'|sh
3

git status outputs relative paths so if you cd to the same directory as the file (under your working directory's root) before running git status it will only output the basenames of added/staged files.

cd /long/path/to/my/repo/root/dir
"stuff" > ./newfile.txt
> git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   /long/path/to/my/repo/root/dir/plus/some/more/levels/of/directory/structure/inside/it/changed_file.txt
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#       long/path/to/my/repo/root/dir/plus/some/even/more/levels/of/directory/structure/inside/it/but_another_new_file.txt
#       newfile.txt
no changes added to commit (use "git add" and/or "git commit -a")

ie, 'newfile.txt' is listed without the full path because you're in the same path as it.

3

git status will always walk down (edit and up) the tree and display relative paths. If you only want the file in the directory you are in, See this related answer

Community
  • 1
  • 1
Dan McClain
  • 11,780
  • 9
  • 47
  • 67
2

In addition to the accepted answer, another way of doing it is with awk

git status --porcelain | awk '{ print $2 }'

The $2 selects second the column of each line.

Gabriel
  • 21
  • 1
0

If you're looking for only the filenames without the path mumbo-jumbo the following should work:

git status --porcelain | cut -c 3- | xargs basename -a

This script gets the shortened format of git status, cuts each line's 3rd column to the end and feeds it to the basename command which outputs only the filename from the full path.

Shababb Karim
  • 3,614
  • 1
  • 22
  • 35
0

If you are using git ls-files, as suggested here by Peter Benjamin, know that, with Git 2.40 (Q1 2023), its options have been clarified.

See commit e750951, commit 4173b80, commit 2b02d2d, commit 2a34b31 (13 Jan 2023) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit 3eda830, 03 Feb 2023)

ls-files: clarify descriptions of file selection options

Signed-off-by: Elijah Newren

The previous descriptions of the file selection options were very easy to misunderstand.
For example:

  • "Show cached files in the output" This could be interpreted as meaning "show files which have been modified and git-add'ed, i.e.
    files which have cached changes relative to HEAD".
  • "Show deleted files" This could be interpreted as meaning "for each git rm $FILE(man) we ran, show me $FILE"
  • "Show modified files" This could be interpreted as meaning "show files which have been modified and git-add'ed" or as "show me files that differ from HEAD" or as "show me undeleted files different from HEAD" (given that --deleted is a separate option), none of which are correct.

Further, it's not very clear when some options only modify and/or override other options, as was the case with --ignored, --directory, and --unmerged (I've seen folks confused by each of them on the mailing list, sometimes even fellow Git developers.)

Tweak these definitions, and the one for --killed, to try to make them all a bit more clear.
Finally, also clarify early on that duplicate reports for paths are often expected (both when (a) there are multiple entries for the file in the index -- i.e.
when there are conflicts, and also (b) when the user specifies options that might pick the same file multiple times, such as git ls-files --cached --deleted --modified``(man) when there is a file with an unstaged deletion).

git ls-files now includes in its man page:

--cached:

Show all files cached in Git's index, i.e. all tracked files. (This is the default if no -c/-s/-d/-o/-u/-k/-m/--resolve-undo options are specified.)

git ls-files now includes in its man page:

--deleted:

Show files with an unstaged deletion

git ls-files now includes in its man page:

--modified:

Show files with an unstaged modification (note that an unstaged deletion also counts as an unstaged modification)

git ls-files now includes in its man page:

--ignored

Show only ignored files in the output.
Must be used with either an explicit '-c' or '-o'.

  • When showing files in the index (i.e. when used with '-c'), print only those files matching an exclude pattern.
  • When showing "other" files (i.e. when used with '-o'), show only those matched by an exclude pattern.

Standard ignore rules are not automatically activated, therefore at least one of the --exclude* options is required.

git ls-files now includes in its man page:

--unmerged:

Show information about unmerged files in the output, but do not show any other tracked files (forces --stage, overrides --cached).

git ls-files now includes in its man page:

--killed

Show untracked files on the filesystem that need to be removed due to file/directory conflicts for tracked files to be able to be written to the filesystem.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250