How can I convert tabs to spaces in every file of a directory?

后端 未结 19 1219
既然无缘
既然无缘 2020-12-02 03:48

How can I convert tabs to spaces in every file of a directory (possibly recursively)?

Also, is there a way of setting the number of spaces per tab?

相关标签:
19条回答
  • 2020-12-02 04:09

    You can use the generally available pr command (man page here). For example, to convert tabs to four spaces, do this:

    pr -t -e=4 file > file.expanded
    
    • -t suppresses headers
    • -e=num expands tabs to num spaces

    To convert all files in a directory tree recursively, while skipping binary files:

    #!/bin/bash
    num=4
    shopt -s globstar nullglob
    for f in **/*; do
      [[ -f "$f" ]]   || continue # skip if not a regular file
      ! grep -qI "$f" && continue # skip binary files
      pr -t -e=$num "$f" > "$f.expanded.$$" && mv "$f.expanded.$$" "$f"
    done
    

    The logic for skipping binary files is from this post.

    NOTE:

    1. Doing this could be dangerous in a git or svn repo
    2. This is not the right solution if you have code files that have tabs embedded in string literals
    0 讨论(0)
  • 2020-12-02 04:09

    My recommendation is to use:

    find . -name '*.lua' -exec ex '+%s/\t/  /g' -cwq {} \;
    

    Comments:

    1. Use in place editing. Keep backups in a VCS. No need to produce *.orig files. It's good practice to diff the result against your last commit to make sure this worked as expected, in any case.
    2. sed is a stream editor. Use ex for in place editing. This avoids creating extra temp files and spawning shells for each replacement as in the top answer.
    3. WARNING: This messes with all tabs, not only those used for indentation. Also it does not do context aware replacement of tabs. This was sufficient for my use case. But might not be acceptable for you.
    4. EDIT: An earlier version of this answer used find|xargs instead of find -exec. As pointed out by @gniourf-gniourf this leads to problems with spaces, quotes and control chars in file names cf. Wheeler.
    0 讨论(0)
  • 2020-12-02 04:10

    I used astyle to re-indent all my C/C++ code after finding mixed tabs and spaces. It also has options to force a particular brace style if you'd like.

    0 讨论(0)
  • 2020-12-02 04:13

    You can use find with tabs-to-spaces package for this.

    First, install tabs-to-spaces

    npm install -g tabs-to-spaces
    

    then, run this command from the root directory of your project;

    find . -name '*' -exec t2s --spaces 2 {} \;
    

    This will replace every tab character with 2 spaces in every file.

    0 讨论(0)
  • 2020-12-02 04:14

    Git repository friendly method

    git-tab-to-space() (
      d="$(mktemp -d)"
      git grep --cached -Il '' | grep -E "${1:-.}" | \
        xargs -I'{}' bash -c '\
        f="${1}/f" \
        && expand -t 4 "$0" > "$f" && \
        chmod --reference="$0" "$f" && \
        mv "$f" "$0"' \
        '{}' "$d" \
      ;
      rmdir "$d"
    )
    

    Act on all files under the current directory:

    git-tab-to-space
    

    Act only on C or C++ files:

    git-tab-to-space '\.(c|h)(|pp)$'
    

    You likely want this notably because of those annoying Makefiles which require tabs.

    The command git grep --cached -Il '':

    • lists only the tracked files, so nothing inside .git
    • excludes directories, binary files (would be corrupted), and symlinks (would be converted to regular files)

    as explained at: How to list all text (non-binary) files in a git repository?

    chmod --reference keeps the file permissions unchanged: https://unix.stackexchange.com/questions/20645/clone-ownership-and-permissions-from-another-file Unfortunately I can't find a succinct POSIX alternative.

    If your codebase had the crazy idea to allow functional raw tabs in strings, use:

    expand -i
    

    and then have fun going over all non start of line tabs one by one, which you can list with: Is it possible to git grep for tabs?

    Tested on Ubuntu 18.04.

    0 讨论(0)
  • 2020-12-02 04:16

    Download and run the following script to recursively convert hard tabs to soft tabs in plain text files.

    Execute the script from inside the folder which contains the plain text files.

    #!/bin/bash
    
    find . -type f -and -not -path './.git/*' -exec grep -Iq . {} \; -and -print | while read -r file; do {
        echo "Converting... "$file"";
        data=$(expand --initial -t 4 "$file");
        rm "$file";
        echo "$data" > "$file";
    }; done;
    
    0 讨论(0)
提交回复
热议问题