How to rename a large number of files

I have a directory with such files

a.JPG b.JPG c.JPG 

I would like to accomplish something like this

 git mv a.JPG a.jpg 

I tried using xargs and other tools, but nothing works.

+7
git command-line
source share
4 answers

The core of the solution will be the use of a tool / method that will automate mass renaming. You can use mv in combination with git add or just git mv. In any case, you may need to take additional steps if you are using a case-insensitive file system. Therefore, before we move on to mass renaming, it may be useful to discuss how the case is handled.

Body sensitivity

Some systems (or system + file system combinations, such as the default option for the HFS + file system on Mac OS X * ) are case-sensitive but not case-sensitive. On such systems, you may need to be careful when creating renames that are only related to changing the name case. The usual workaround is to use a temporary name, which is not just a case of a β€œbridge” between two names that differ in only one case (for example, mv foo.JPG tmp && mv tmp foo.jpg ).

* You can use case-sensitive file systems on Mac OS X (including the case-sensitive version of HFS +).

Now I will read the file system without a register.

The mv command on Mac OS X can handle shift renames for only one step. This will give a "rewrite?". prompt, if executed with the -i option, and will skip renaming if -n is specified. This is only achieved thanks to the "enough rope to hang" by default of many parts of Unix-like systems.

The git mv command is a bit more paranoid regarding the situation. It refuses the operation (error "destination exists") if the -f / --force option is not specified.

 # this will succeed, though it may fail/prompt if mv is aliased to use -n/-i mv foo.JPG foo.jpg # this will succeed mv -f bar.JPG bar.jpg # this will succeed but give a warning git mv -f quux.JPG quux.jpg 

Package Rename Options

Perl rename

The desired operation is simple enough to work with a small number of shell scripts, but you can get the Perl rename utility (the one Jordan Lewis talks about) if you need to do something much more complicated. You can try renaming from the Debian perl package , or if you feel that you are using CPAN, you can install File :: Rename , which includes a rename program.

ksh, bash, zsh, dash

The -ef used below -ef not POSIX compatible. Similarly, while -e is specified on POSIX, it is not Bourne compatible. Both are widely supported.

 for f in *.JPG; do ff="${f%.JPG}.jpg" test -e "$f" || continue # possible when not using nullglob test "$f" != "$ff" || continue # possible when using nocaseglob if test -e "$ff" && ! test "$f" -ef "$ff"; then # possible on a case sensitive filesystem echo "skipping <$f>: destination <$ff> exists and is distinct" 1>&2 continue fi # "mv" with "git rm" and "git add" mv -f "$f" "$ff" && git rm --cached "$f" && git add "$ff" done 

The last section (mv, git rm, git add) can be replaced simply by git mv:

  # "git mv" git mv -f "$f" "$ff" 

If you are very concerned about how renaming can fail on case insensitive systems, you can use a temporary name:

  # temp-based "mv" with "git rm" and "git add" t="$ff.tmp"; while test -e "$t"; do t="$t.tmp"; done mv -n "$f" "$t" && mv -n "$t" "$ff" && git rm --cached "$f" && git add "$ff" 

Or using git mv:

  # temp-based "git mv" t="$ff.tmp"; while test -e "$t"; do t="$t.tmp"; done git mv "$f" "$t" && git mv "$t" "$ff" 

ZS / & # xfeff; Zmv

This needs -f for zmv and git mv.

 zsh -c 'autoload zmv && $0 $@' zmv -fp git -o 'mv -f' '(*).JPG' '$1 x.jpg' 

Now that you have renamed them and updated them in the git index, you can commit them.

But will other git users be able to use case sensitive filesystems?

git checkout After renaming only for case

If there are other users of your story, they are likely to still have JPG files and when they eventually select (a descendant) your commit with JPG files. What will happen to them?

No matter what happens, there is no need to "rename temp, commit, rename final, commit". git check is not applied, it performs a sequence when moving between commits. This really works by "merging" the index and the working tree from HEAD to the new commit. This actually means that it β€œjumps” directly to the new commit when dragging non-contradictory changes between the HEAD and the index / work tree.

Inside, git views are renamed as delete and add. I did not find documentation describing the behavior of the git check regarding the order of removal and addition, so I looked at the source code. git checkout handles all deletions before any updates / additions (cmd_checkout β†’ switch_branches β†’ merge_working_tree (-> reset_tree) β†’ unpack_trees β†’ check_updates ).

You can check this right after renaming:

 git checkout HEAD~ # note: detached HEAD # verify that the original names are back in place git checkout - # back to your branch # verify that the new names are in place again 

The git fault in the file seemed to indicate a likely commit: Make deleted files to unpack the tree before any updated files that were first released in git 1.5.6-rc0 (2008-06-18). Thus, although this is undocumented (?), This behavior has been implemented specifically to support case-insensitive file systems.

Thanks Linus!

+7
source share

Regardless of whether you can simply change the file case, it depends on your file system. Even if it works on your file system, you can cause problems for other users. Your best bet is to rename them, commit them, and then rename them. Change everything to * .tmp with the following bash script:

 for i in *.JPG; do mv $i ${i%.JPG}.tmp; done 

Then move them all to git. You can use a similar command, but I would recommend checking out guess-renames to help with this move.

Then rename all of them back to * .jpg with a similar process.

+3
source share

Use the standard Linux rename utility (1). After you rename the files, git add them.

+2
source share

Perhaps rename them to * .somethingelse and then rename them back to * .jpg

+1
source share

All Articles