Giter VIP home page Giter VIP logo

brename's Introduction

brename: batch renaming safely

Built with GoLang Go Report Card Cross-platform Latest Version Github Releases

brename is a cross-platform command-line tool for safely batch renaming files/directories via regular expression.

Table of Contents

Features

  • Cross-platform. Supporting Windows, Mac OS X and Linux,

    • Windows file systems, including NTFS and FAT, are case-insensitive. Some operations are allowed on Linux, while they could be dangerous on Windows. For example, renaming test.tar.gz to test.tar will overwrite TEST.tar. brename (v2.13.0 and later versions) can handle these cases appropriately (-w and -W).
  • Safe. It helps you check potential conflicts and errors before it's too late.

    Some common conflict and errors that might happen with commands like mv or rename.

    • New path existed: Existed files might be overwritten, causing data loss.
    • Overwriting newly renamed path. Existed files might be overwritten, causing data loss. This case is hard to check by eyes.
    • Missing target: New file is empty, that's not allowed.
    • New path ending with a space: Not allowed in Windows. It's legal in Linux, but might cause unexpected errors.
    • New path ending with a period: Not allowed in Windows.
  • Supporting dry run. A good habbit.

  • Supporting Undo the LAST successful operation, like a time machine.

  • Overwrite can be detected and users can choose whether overwrite or leave it (-o/--overwrite-mode).

  • File filtering.

    • Supporting including (-f/--include-filters) and excluding (-F/--exclude-filters) files via regular expression.
    • No need to run commands like find ./ -name "*.html" -exec CMD.
  • Renaming submatch with corresponding value via key-value file (-r "{kv}" -k kv.tsv).

  • Renaming via ascending integer (-r "{nr}").

  • Automatically making directoy: e.g., renaming a-b-c.txt to a/b/c.txt.

  • Recursively renaming both files and directories (-R/--recursive, -D/--including-dir, --only-dir).

Installation

brename is implemented in Go programming language, executable binary files for most popular operating systems are freely available in release page.

Method 1: Download binaries

brename v2.14.0 Github Releases (by Release)

Tip: run brename -V to check update !!!

OS Arch File, **镜像 Download Count
Linux 32-bit brename_linux_386.tar.gz,
**镜像
Github Releases (by Asset)
Linux 64-bit brename_linux_amd64.tar.gz,
**镜像
Github Releases (by Asset)
Linux arm64 brename_linux_arm64.tar.gz,
**镜像
Github Releases (by Asset)
OS X 64-bit brename_darwin_amd64.tar.gz,
**镜像
Github Releases (by Asset)
OS X arm64 brename_darwin_arm64.tar.gz,
**镜像
Github Releases (by Asset)
Windows 32-bit brename_windows_386.exe.tar.gz,
**镜像
Github Releases (by Asset)
Windows 64-bit brename_windows_amd64.exe.tar.gz,
**镜像
Github Releases (by Asset)

Just download compressed executable file of your operating system, and decompress it with tar -zxvf *.tar.gz command or other tools. And then:

  1. For Linux-like systems

    1. If you have root privilege simply copy it to /usr/local/bin:

       sudo cp brename /usr/local/bin/
      
    2. Or copy to anywhere in the environment variable PATH:

       mkdir -p $HOME/bin/; cp brename $HOME/bin/
      
  2. For windows, just copy brename.exe to C:\WINDOWS\system32.

Method 2: For Go developer

go get -u github.com/shenwei356/brename/

Method 3: For ArchLinux AUR users

yaourt -S brename

Method 4: For Scoop users

scoop install brename

Method 5: Compiling from source

# download Go from https://go.dev/dl
wget https://go.dev/dl/go1.17.13.linux-amd64.tar.gz

tar -zxf go1.17.13.linux-amd64.tar.gz -C $HOME/

# or 
#   echo "export PATH=$PATH:$HOME/go/bin" >> ~/.bashrc
#   source ~/.bashrc
export PATH=$PATH:$HOME/go/bin

git clone https://github.com/shenwei356/brename
cd brename

go build

# or statically-linked binary
CGO_ENABLED=0 go build -tags netgo -ldflags '-w -s'

# or cross compile for other operating systems and architectures
CGO_ENABLED=0 GOOS=openbsd GOARCH=amd64 go build -tags netgo -ldflags '-w -s'

Usage


brename: a practical cross-platform command-line tool for safely batch renaming files/directories via regular expression

Version: 2.14.0

Author: Wei Shen <[email protected]>

Homepage: https://github.com/shenwei356/brename

Warnings:
  1. The path in file systems like FAT32 or NTFS is case-insensitive, so you should switch on the flag
     -w/--case-insensitive-path to correctly check file overwrites.
  2. The flag -w/--case-insensitive-path is switched on by default on Windows, please use
     -W/--case-sensitive-path to disable it if the file system is indeed case-sensitive.
  3. New paths ending with periods of spaces, being error-prone, are not allowed.

Three path filters:

  1. -S/--skip-filters       black list     default value: ^\. (skipping paths starting with ".")
  2. -F/--exclude-filters    black list     no default value
  3. -f/--include-filters    white list     default value: .   (anything)

  Notes:
  1. Paths starting with "." are ignored by default, disable this with -S "".
  2. These options support multiple values, e.g., -f ".html" -f ".htm".
     But ATTENTION: each comma in filters is treated as a separator of multiple filters.
     Please use double quotation marks for patterns containing comma, e.g., -p '"A{2,}"'
  3. The three filters are performed in order of -S, -F, -f.
  4. -F/--exclude-filters is prefered for excluding path, cause it has no default value.
     Setting -S/--skip-filters will overwrite its default value.


Special replacement symbols:

  {nr}    Ascending integer
  {kv}    Corresponding value of the key (captured variable $n) by key-value file,
          n can be specified by flag -I/--key-capt-idx (default: 1)

Special cases of replacement string:
 *1. Capture variables should be in the format of '${1}' to reduce errors.
    a). If the capture variable is followed with space or other simple, it's OK:
            -r '$1 abc'
    b). If followed by numbers, characters, or underscore. That is ambiguous:
            -r '$1abc' actually refers to the variable '1abc', please use '${1}abc'.
            -r '$2_$1' actually refers to the variable '2_', please use '${2}_${1}'.
  2. Want to replace with a character '$',
    a). If using '{kv}', you need use '$$$$' instead of a single '$':
            -r '{kv}' -k <(sed 's/\$/$$$$/' kv.txt)
    b). If not, use '$$'. e.g., adding '$' to all numbers:
            -p '(\d+)' -d -r '$$${1}'

Usage:
  brename [flags]

Examples:
  1. dry run and showing potential dangerous operations (-d)
      brename -p "abc" -d
  2. dry run and only show operations that will cause error (-v)
      brename -p "abc" -d -v 2
  3. only renaming specific paths via include filters (-f)
      brename -p ":" -r "-" -f ".htm$" -f ".html$"
  4. renaming all .jpeg files to .jpg in all subdirectories (-R)
      brename -p "\.jpeg" -r ".jpg" -R   dir
  5. using capture variables, e.g., $1, $2 ...
      brename -p "(a)" -r "\$1\$1"
      or brename -p "(a)" -r '$1$1' in Linux/Mac OS X
  6. renaming directory too (-D)
      brename -p ":" -r "-" -R -D   pdf-dirs
  7. using key-value file (-k)
      brename -p "(.+)" -r "{kv}" -k kv.tsv
  8. do not touch file extension (-e)
      brename -p ".+" -r "{nr}" -f .mkv -f .mp4 -e
  9. only list paths that match pattern (-l)
      brename -i -f '.docx?$' -p . -R -l
  10. undo the LAST successful operation (-u)
      brename -u
  11. disable undo if you do not want to create .brename_detail.txt (-x)
      brename -p xxx -r yyy -x
  12. clear/remove all .brename_detail.txt files (--clear)
      brename --clear -R
  13. also operate on hidden files: empty -S (default: ^\.)
      brename -p xxx -r yyy -S ""

  More examples: https://github.com/shenwei356/brename

Flags:
  -w, --case-insensitive-path     the file system (e.g., FAT32 or NTFS) is case-insensitive. It's
                                  automatically swiched on on Windows
  -W, --case-sensitive-path       believing that the file system is case-sensitive. Please use this to
                                  disable the flag -w/--case-insensitive-path, which is switched on by
                                  default on Windows
      --clear                     remove all .brename_detail.txt" file, you may need to add
                                  -R/--recursive to recursively clear all files in the given path
  -x, --disable-undo              do not create .brename_detail.txt file for undo
  -d, --dry-run                   print rename operations but do not run
  -F, --exclude-filters strings   exclude file filter(s) (regular expression, NOT wildcard). multiple
                                  values supported, e.g., -F ".html" -F ".htm", but ATTENTION: each
                                  comma in the filter is treated as the separator of multiple filters,
                                  please use double quotation marks for patterns containing comma, e.g.,
                                  -p '"A{2,}"'
  -U, --force-undo                continue undo even when some operations failed
  -h, --help                      help for brename
  -i, --ignore-case               ignore case of -p/--pattern, -f/--include-filters and -F/--exclude-filters
  -E, --ignore-err                ignore director reading errors
  -e, --ignore-ext                ignore file extension. i.e., replacement does not change file extension
  -f, --include-filters strings   include file filter(s) (regular expression, NOT wildcard). multiple
                                  values supported, e.g., -f ".html" -f ".htm", but ATTENTION: each
                                  comma in the filter is treated as the separator of multiple filters,
                                  please use double quotation marks for patterns containing comma, e.g.,
                                  -p '"A{2,}"' (default [.])
  -D, --including-dir             rename directories
  -K, --keep-key                  keep the key as value when no value found for the key
  -I, --key-capt-idx int          capture variable index of key (1-based) (default 1)
  -m, --key-miss-repl string      replacement for key with no corresponding value
  -k, --kv-file string            tab-delimited key-value file for replacing key with value when using
                                  "{kv}" in -r (--replacement)
  -l, --list                      only list paths that match pattern
  -a, --list-abs                  list absolute path, using along with -l/--list
  -s, --list-sep string           separator for list of found paths (default "\n")
      --max-depth int             maximum depth for recursive search (0 for no limit)
  -N, --nature-sort               list paths in nature sort, using along with -l/--list
      --nr-width int              minimum width for {nr} in flag -r/--replacement. e.g., formating "1"
                                  to "001" by --nr-width 3 (default 1)
      --only-dir                  only rename directories
  -o, --overwrite-mode int        overwrite mode (0 for reporting error, 1 for overwrite, 2 for not
                                  renaming) (default 0)
  -p, --pattern string            search pattern (regular expression)
  -q, --quiet                     be quiet, do not show any information and warning
  -R, --recursive                 rename recursively
  -r, --replacement string        replacement. capture variables supported.  e.g. $1 or ${1} (prefered)
                                  represents the first submatch. ATTENTION: for *nix OS, use SINGLE
                                  quote NOT double quotes or use the \ escape character. Ascending
                                  integer is also supported by "{nr}"
  -S, --skip-filters strings      skip file filter(s) (regular expression, NOT wildcard). multiple
                                  values supported, e.g., -S "^\." for skipping files starting with a
                                  dot, but ATTENTION: each comma in the filter is treated as the
                                  separator of multiple filters, please use double quotation marks for
                                  patterns containing comma, e.g., -p '"A{2,}"' (default [^\.])
  -n, --start-num int             starting number when using {nr} in replacement (default 1)
  -u, --undo                      undo the LAST successful operation
  -v, --verbose int               verbose level (0 for all, 1 for warning, error and renamed files, 2
                                  for only error and renamed files) (default 2)
  -V, --version                   print version information and check for update

Examples

Take a directory for example (run generate-example-folder.sh to generate)

$ sh generate-example-folder.sh 
example
├── abc
│   ├── A.JPEG
│   ├── B.HTM
│   └── B.JPEG
├── a.html
├── a.jpeg
└── b.jpeg

# examples below were executed in directory: example
cd example/
  1. Recursively renaming all .jpeg files to .jpg in all subdirectories (-R/--recursive). A dry run is firstly performed for safety checking (-d/--dry-run).

     $ brename -p "\.jpeg" -r ".jpg" -R -d
     Searching for paths to rename...
    
       [OK] example/a.jpeg -> example/a.jpg
       [OK] example/b.jpeg -> example/b.jpg
    
     2 path(s) to be renamed
    
    
     $ brename -p "\.jpeg" -r ".jpg" -R
     Searching for paths to rename...
    
       Done searching.
    
     Renaming paths...
    
       [DONE] example/a.jpeg -> example/a.jpg
       [DONE] example/b.jpeg -> example/b.jpg
    
     2 path(s) renamed in 0.001 seconds
    
     $ tree
     .
     ├── abc
     │   ├── A.JPEG
     │   ├── B.HTM
     │   └── B.JPEG
     ├── a.html
     ├── a.jpg
     └── b.jpg
    
  2. Undo the LAST successful operation, yes it's COOL! (-u/--undo, -U/--force-undo)

     $ brename -u
     Renaming paths back...
    
       [DONE] example/b.jpg -> example/b.jpeg
       [DONE] example/a.jpg -> example/a.jpeg
    
     2 path(s) renamed back in 0.000 seconds
    

    Disable undo if you do not want to create .brename_detail.txt (-x)

     $ brename -p xxx -r yyy -x
    

    Clear/remove all .brename_detail.txt files (--clear)

     $ brename --clear -R
    
  3. Dry run, only showing operations that will cause error (just remove -d).

     # default value of -v is 0
     $ brename -p a -r b -R -D -d
     Searching for paths to rename...
    
       [OK] a.html -> b.html
       [new path existed] a.jpeg -> b.jpeg
       [OK] abc -> bbc
    
     1 potential error(s) detected, please check
    
     $ brename -p a -r b -R -D
     Searching for paths to rename...
    
       Done searching.
       [new path existed] example/a.jpeg -> example/b.jpeg
    
     1 potential error(s) detected, please check
    
  4. Ignoring cases (-i/--ignore-case)

     $ brename -p "\.jpeg" -r ".jpg" -R -i
     Searching for paths to rename...
    
       Done searching.
    
     Renaming paths...
    
       [DONE] abc/A.JPEG -> abc/A.jpg
       [DONE] abc/B.JPEG -> abc/B.jpg
    
     2 path(s) renamed in 0.000 seconds
    
    
     $ tree
     .
     ├── abc
     │   ├── A.jpg
     │   ├── B.HTM
     │   └── B.jpg
     ├── a.html
     ├── a.jpg
     └── b.jpg
    
  5. Using capture variables, e.g., $1, $2 ...

     # or brename -p "(a)" -r '$1$1' in Linux/Mac OS X
     $ brename -p "(a)" -r "\$1\$1" -i
     Searching for paths to rename...
    
       Done searching.
    
     Renaming paths...
    
       [DONE] a.html -> aa.html
       [DONE] a.jpg -> aa.jpg
    
     2 path(s) renamed in 0.000 seconds
    
     $ tree
     .
     ├── aa.html
     ├── aa.jpg
     ├── abc
     │   ├── A.jpg
     │   ├── B.HTM
     │   └── B.jpg
     └── b.jpg
    
  6. Renaming directory too (-D/--including-dir), even renaming directory only (-D --only-dir)

     $ brename -p "a" -r "A" -R -D
     Searching for paths to rename...
    
       Done searching.
    
     Renaming paths...
    
       [DONE] aa.html -> AA.html
       [DONE] aa.jpg -> AA.jpg
       [DONE] abc -> Abc
    
     3 path(s) renamed in 0.001 seconds
    
     $ tree
     .
     ├── AA.html
     ├── AA.jpg
     ├── Abc
     │   ├── A.jpg
     │   ├── B.HTM
     │   └── B.jpg
     └── b.jpg
    
  7. Only renaming specific files via include filters (regular expression) (-f/--include-filters)

     $ brename -p '(.)' -r ' $1' -d
     Searching for paths to rename...
    
       [OK] AA.html ->  A A . h t m l
       [OK] AA.jpg ->  A A . j p g
       [OK] b.jpg ->  b . j p g
    
     3 path(s) to be renamed
    
    
     
     $ brename -p '(.)' -r ' $1' -d -f '\.jpg$'
     Searching for paths to rename...
    
       [OK] AA.jpg ->  A A . j p g
       [OK] b.jpg ->  b . j p g
    
     2 path(s) to be renamed
    

    Attention: value of -f/--include-filters and -F/--exclude-filters should be regular expression, NOT wildcard!

     $ brename -p '(.)' -r '$1 ' -d -f *.jpg
     Seems you are using wildcard for -f/--include-filters? Make sure using regular expression: AA.jpg
     Searching for paths to rename...
    
    
     0 path(s) to be renamed
     
     $ brename -p '(.)' -r '$1 ' -d -f '*.jpg'
     Are you using wildcard for -f/--include-filters? It should be regular expression: *.jpg
     illegal regular expression for include filter: *.jpg
     
     $ brename -p '(.)' -r '$1 ' -d -f A*
     Seems you are using wildcard for -f/--include-filters? Make sure using regular expression: AA.html
     Searching for paths to rename...
    
    
     0 path(s) to be renamed
    
  8. Excluding files via exclude filters (regular expression) (-F/--exclude-filters)

     $ brename -p '(.)' -r ' $1' -d
     Searching for paths to rename...
    
       [OK] AA.html ->  A A . h t m l
       [OK] AA.jpg ->  A A . j p g
       [OK] b.jpg ->  b . j p g
    
     3 path(s) to be renamed
    
    
     $ brename -p '(.)' -r ' $1' -d -F '\.html$'
     Searching for paths to rename...
    
       [OK] AA.jpg ->  A A . j p g
       [OK] b.jpg ->  b . j p g
    
     2 path(s) to be renamed
    
  9. Skipping files via skip filter (regular expression) (-S/--skip-filters). This filter step is performed before the exclude filters. The default value ^\. is for skipping files starting with dot, which are hidden configuration files in Linux. If you do not want to skip these paths, just empty it.

     $ brename -p xxx -r yyy -S ""
    
  10. Do not touch file extension (-e/--ignore-ext)

     $ brename -p '(.)' -r ' $1' -d
     Searching for paths to rename...
    
       [OK] AA.html ->  A A . h t m l
       [OK] AA.jpg ->  A A . j p g
       [OK] b.jpg ->  b . j p g
    
     3 path(s) to be renamed
    
     $ brename -p '(.)' -r ' $1' -d -e
     Searching for paths to rename...
    
       [OK] AA.html ->  A A.html
       [OK] AA.jpg ->  A A.jpg
       [OK] b.jpg ->  b.jpg
    
     3 path(s) to be renamed
    
  11. Renaming with number (-r {nr})

     $ brename -d -p '(.+)\.' -r 'pic-{nr}.' -f .jpg -d
     Searching for paths to rename...
    
       [OK] AA.jpg -> pic-1.jpg
       [OK] b.jpg -> pic-2.jpg
    
     2 path(s) to be renamed
    
    
     $ brename -d -p '(.+)\.' -r 'pic-{nr}.' -f .jpg -d --nr-width 3 --start-num 11
     Searching for paths to rename...
    
       [OK] AA.jpg -> pic-011.jpg
       [OK] b.jpg -> pic-012.jpg
    
     2 path(s) to be renamed
    
  12. Replace submatch with corresponding value via tab delimited key-value file (-k/--kv-file)

     $ more kv.tsv
     a       一
     b       二
     c       三
    
     $ brename -p '^(\w)' -r '{kv}' -k kv.tsv -K -i -d
     read key-value file: kv.tsv
     3 pairs of key-value loaded
     Searching for paths to rename...
    
       [OK] AA.html -> 一A.html
       [OK] AA.jpg -> 一A.jpg
       [OK] b.jpg -> 二.jpg
       [unchanged] kv.tsv -> kv.tsv
    
     3 path(s) to be renamed
    
  13. Auto mkdir

     $ touch a-b-c.txt
    
     $ brename -f .txt -p '-' -r '/'
     Searching for paths to rename...
    
       Done searching.
    
     Renaming paths...
    
       [DONE] a-b-c.txt -> a/b/c.txt
    
     1 path(s) renamed in 0.000 seconds
    
     $ tree a
     a
     └── b
         └── c.txt
    
  14. Only listing paths that match pattern (-l and -a)

     $ brename -p '.gz$' -R -l
     binaries/brename_darwin_386.tar.gz
     binaries/brename_darwin_amd64.tar.gz
     binaries/brename_linux_386.tar.gz
     binaries/brename_linux_amd64.tar.gz
     binaries/brename_windows_386.exe.tar.gz
     binaries/brename_windows_amd64.exe.tar.gz
    
     $ brename -p '.gz$' -R -l -a
     /home/shenwei/project/src/github.com/shenwei356/brename/binaries/brename_darwin_386.tar.gz
     /home/shenwei/project/src/github.com/shenwei356/brename/binaries/brename_darwin_amd64.tar.gz
     /home/shenwei/project/src/github.com/shenwei356/brename/binaries/brename_linux_386.tar.gz
     /home/shenwei/project/src/github.com/shenwei356/brename/binaries/brename_linux_amd64.tar.gz
     /home/shenwei/project/src/github.com/shenwei356/brename/binaries/brename_windows_386.exe.tar.gz
     /home/shenwei/project/src/github.com/shenwei356/brename/binaries/brename_windows_amd64.exe.tar.gz
    
  15. Overwrite mode (-o/--overwrite-mode)

     $ ls *.tar.gz
     brename_darwin_386.tar.gz    brename_linux_386.tar.gz    brename_windows_386.exe.tar.gz
     brename_darwin_amd64.tar.gz  brename_linux_amd64.tar.gz  brename_windows_amd64.exe.tar.gz
    
    1. default mode: reporting error

       $ brename -p 386 -r amd64 -d
       Searching for paths to rename...
      
         [new path existed] brename_linux_386.tar.gz -> brename_linux_amd64.tar.gz
         [new path existed] brename_windows_386.exe.tar.gz -> brename_windows_amd64.exe.tar.gz
      
       2 potential error(s) detected, please check
      
    2. allowing overwrite

       $ brename -p 386 -r amd64 -d -o 1
       Searching for paths to rename...
      
         [new path existed] brename_linux_386.tar.gz -> brename_linux_amd64.tar.gz (will be overwrited)
         [new path existed] brename_windows_386.exe.tar.gz -> brename_windows_amd64.exe.tar.gz (will be overwrited)
      
       2 path(s) to be renamed
      
    3. leave it

       $ brename -p 386 -r amd64 -d -o 2
       Searching for paths to rename...
      
         [new path existed] brename_linux_386.tar.gz -> brename_linux_amd64.tar.gz (will NOT be overwrited)
         [new path existed] brename_windows_386.exe.tar.gz -> brename_windows_amd64.exe.tar.gz (will NOT be overwrited)
      
       0 path(s) to be renamed
      

Real-world examples

  1. Formating genome assembly file from NCBI.

     $ ls 
     GCF_029211165.1_ASM2921116v1_genomic.fa
    
     # ------------------------------------------------------------------------
     # only keeping accession
    
     Searching for paths to rename...
    
     [OK] GCF_029211165.1_ASM2921116v1_genomic.fa -> GCF_029211165.fa
    
     1 path(s) to be renamed
    
     # ------------------------------------------------------------------------
     # keeping accession.version
     
     $ brename -R -p '^(\w{3}_\d{9}\.\d+).+' -r '$1.fa' -d
     Searching for paths to rename...
    
       [OK] GCF_029211165.1_ASM2921116v1_genomic.fa -> GCF_029211165.1.fa
    
     1 path(s) to be renamed
    
  2. Replace matches with corresponding pairing values

    1. Original files

       $ tree
       .
       ├── barcodes.tsv
       ├── tag_ATGCGTA.fasta
       ├── tag_CCCCCCC.fasta
       ├── tag_CGACGTC.fasta
       ├── tag_TCATAGC.fasta
       └── tag_TCTATAG.fasta
      
    2. Tab-delimited key-value file. Notice that CCCCCCC is not in it.

       $ cat barcodes.tsv
       CGACGTC S1
       ATGCGTA S2
       TCTATAG S4
       TCATAGC S3
      
    3. Renaming tag as sample name, marking unknown for non-existing tag.

       $ brename -e -p 'tag_(\w+)' -r '{kv}' -k barcodes.tsv -m unknown -d
       [INFO] read key-value file: barcodes.tsv
       [INFO] 4 pairs of key-value loaded
       [INFO] checking: [ ok ] 'tag_ATGCGTA.fasta' -> 'S2.fasta'
       [INFO] checking: [ ok ] 'tag_CCCCCCC.fasta' -> 'unknown.fasta'
       [INFO] checking: [ ok ] 'tag_CGACGTC.fasta' -> 'S1.fasta'
       [INFO] checking: [ ok ] 'tag_TCATAGC.fasta' -> 'S3.fasta'
       [INFO] checking: [ ok ] 'tag_TCTATAG.fasta' -> 'S4.fasta'
       [INFO] 5 path(s) to be renamed
      
  3. Renaming PDF files for compatibility (moving from EXT4 to NTFS file system):

    1. Original files

       $ tree -Q
       .
       ├── "0000 Test.pdf"
       ├── "2016 SeqKit: A Cross-Platform and Ultrafast Toolkit for FASTA\342\201\204Q File Manipulation .pdf"
       ├── "metagenomics"
       │   ├── "2017 16S rRNA gene sequencing and healthy reference ranges for 28 clinically relevant microbial taxa from the human gut microbiome .pdf"
       │   ├── "2017 De novo assembly of viral quasispecies using overlap graphs .pdf"
       │   └── "2017 Tracking microbial colonization in fecal microbiota transplantation experiments via genome-resolved metagenomics .pdf"
       ├── "test2222222222222222222211111111122222222222222222233333333.pdf"
       └── "test.pdf"
      
    2. Removing "\n", "'", "?".

       $ brename -p "[\n'\?]" -r " " -R
      
    3. Replacing ":" with " _"

       $ brename -p ":" -r " _" -R
      
    4. Shortening file names (prefering spliting with space)

       $ brename -R -f .pdf -i -p "^(.{30,50})[ \.].*.pdf" -r "\$1.pdf" -d
      
    5. Result

       $ tree -Q
       .
       ├── "0000 Test.pdf"
       ├── "2016 SeqKit _ A Cross-Platform and Ultrafast.pdf"
       ├── "metagenomics"
       │   ├── "2017 16S rRNA gene sequencing and healthy.pdf"
       │   ├── "2017 De novo assembly of viral quasispecies using.pdf"
       │   └── "2017 Tracking microbial colonization in fecal.pdf"
       ├── "test2222222222222222222211111111122222222222222222233333333.pdf"
       └── "test.pdf"
      

FAQs

Contact

Create an issue to report bugs, propose new functions or ask for help.

License

MIT License

Starchart

Stargazers over time

brename's People

Contributors

efournival avatar jfastnacht avatar mattn avatar qqii avatar shenwei356 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

brename's Issues

Segmentation Fault upon execution in OpenBSD 6.9

Obviously, this is an extremely handy script that I have enjoyed using for years. Unfortunately, I have not used it lately. So, when I got back around to using it, I updated to the newest release and attempted a dry run:

brename -p "\.php" -r "\.jpg" -d
[1]    35399 segmentation fault  /home/user/go/bin/brename -p "\.php" -r ".jpg" -d

Then I tried to see what could have caused the issue and how to enable verbose output by accessing help:

brename --help                  
[1]    84355 segmentation fault  /home/user/go/bin/brename --help

brename -h                  
[1]    84355 segmentation fault  /home/user/go/bin/brename -h

Even if I just enter the command brename the result is 31825 segmentation fault. Not sure how to best approach troubleshooting this further. Let me know what else I can do or what other information I can provide to best assist in resolving this bug.

I am currently running OpenBSD 6.9 with go version go1.16.6 openbsd/amd64 in zsh 5.8 (x86_64-unknown-openbsd6.9)

Skip errors

If I'm renaming a lot of files, I don't want a few errors to stop the process. I would like an option which just skips those renames, and continues renaming files.

Issue when working on external drive

I have a USB SSD drive. I'm a folder in it similar to: /Volumes/SD-250G-SSD/MyProject/MyFolder/MySubFolder/AndSubSubFolder. brename commands don't work within it - it just doesn't match the patterns. If I copy the files, say, to /tmp and then run the same command, it works.

Windows: brename doesn't detect when files will be overwritten if the replacement only differs in case

Using brename v2.12.0 on Windows.
Create two files, test.txt and test.doc.

brename -x -p "\..+$" -r "" -d

[INFO] checking: [ ok ] 'test.doc' -> 'test'
[ERRO] checking: [ overwriting newly renamed path ] 'test.txt' -> 'test'
[ERRO] 1 potential error(s) detected, please check

This works as expected. Now create test.txt and Test.doc.

brename -x -p "\..+$" -r "" -d

[INFO] checking: [ ok ] 'Test.doc' -> 'Test'
[INFO] checking: [ ok ] 'test.txt' -> 'test'
[INFO] 2 path(s) to be renamed

Now do the rename:

brename -x -p "\..+$" -r ""

[INFO] renamed: 'Test.doc' -> 'Test'
[INFO] renamed: 'test.txt' -> 'test'
[INFO] 2 path(s) renamed

Only one file remains in the directory, because NTFS is case insensitive.

Invalid result with capture variables

I have the following files in my folder:

pic_F01P01.jpg
pic_F01P02.jpg
pic_F01P03.jpg

I want to obtain:

F01P01.jpg
F01P02.jpg
F01P03.jpg

I was expecting this command to work, but it's not:

brename -p ".*F(\d\d)P(\d\d).*\.jpg" -r 'F$1P$2.jpg' -d
Searching for paths to rename...

  [OK] pic_F01P01.jpg -> F01.jpg
  [OK] pic_F01P02.jpg -> F02.jpg
  [OK] pic_F01P03.jpg -> F03.jpg

3 path(s) to be renamed

If i add a non alpha character to separate the $1 and the P, it works:

brename -p ".*F(\d\d)P(\d\d).*\.jpg" -r 'F$1-P$2.jpg' -d
Searching for paths to rename...

  [OK] pic_F01P01.jpg -> F01-P01.jpg
  [OK] pic_F01P02.jpg -> F01-P02.jpg
  [OK] pic_F01P03.jpg -> F01-P03.jpg

3 path(s) to be renamed

Exact same thing happens if i use -r "F\$1P\$2.jpg"
I'm on Ubuntu 22.04.3

Please integrate with git

If renamed files are in the git repository, run git mv instead of just mv.

brename can auto-detect that (1) the git program is present (2) directory is inside of the git repository and (3) files are members of that repository. Then braneme should warn the user that it can either just rename files, or rename them as members of the git repository.

If -g (git integration) flag is given, brename would just run git mv on qualifying files.

renaming files and including folder/directory name in it

Hello,

I have 500 folders and each folder contains about 5 files. I want to rename those files and include folder name with it.

For example:

My folders (sample1_1, sample2_2, sample3_3) look like this:

sample1_1: bin.1.permissive.fa bin2.orig.fa
sample2_2: bin.1.permissive.fa bin2.orig.fa
sample3_3: bin.1.permissive.fa bin2.orig.fa

Now, I want to rename in a way that files look like this:

sample1_1: sample1_bin.1.fa sample1_bin2.fa

In other words, I need the following 2 things to be changed:

  1. Include folder name in the file but after removing last part of it.
  2. Remove middle part of the file i.e. permissive, orig etc.

I couldn't find this type of data in your examples otherwise your renaming tools looks great.

Many thanks in advance!

2.13 output became too verbose

Windows 7 x64 user here.

$ brename2.12.exe -S "" -R -p "\.startup" -r "_startup"

[INFO] main options:
[INFO]   ignore case: false
[INFO]   search pattern: \.startup
[INFO]      skip filters:
[INFO]   include filters: .
[INFO]   search paths: ./
[INFO]
[INFO] checking: [ ok ] 'Keepass\.startup' -> 'Keepass\_startup'
[INFO] 1 path(s) to be renamed
[INFO] renamed: 'Keepass\.startup' -> 'Keepass\_startup'
[INFO] 1 path(s) renamed

Except for the redundant checking and nerdy rather than vernacular presentation of renaming conditions with too much [INFO] SHOUTING, I'm happy with it. Especially considering that @shenwei356 implemented my proposal about undoing changes.

Now, let's update to 2.13 and see what happens.

$ brename2.13.exe -S "" -R -p "\.startup" -r "_startup"

[INFO] brename v2.13.0
[INFO]
[WARN]
[WARN] The flag -w/--case-insensitive-path is switched on Windows by default,
[WARN] where the path is case-insensitive in file systems like FAT32 and NTFS.
[WARN] If you are using a file system in which paths are case-insensitive,
[WARN] please use -W/--case-sensitive-path.
[WARN]
[INFO] ---------------- main options ------------------------
[INFO]
[INFO] search mode:
[INFO]  recursively rename: true
[INFO]       maximum depth: 0 (0 for no limit)
[INFO]   include directory: false
[INFO]      only directory: false
[INFO]
[INFO] path filters and search pattern:
[INFO]    search pattern: \.startup
[INFO]       replacement: _startup
[INFO]       ignore case: false
[INFO]
[INFO]      skip filters:
[INFO]   include filters: .
[INFO]
[INFO] path overwrite checking:
[INFO]   case-insensitive path: true
[INFO]          overwrite mode: 0 (reporting error)
[INFO]
[INFO] miscellaneous:
[INFO]      disable undo: false
[INFO]   only list paths: false
[INFO]           dry run: false
[INFO]
[INFO] ------------------------------------------------------
[INFO]
[INFO] search paths: ./
[INFO]
[INFO] checking: [ ok ] 'Keepass\.startup' -> 'Keepass\_startup'
[INFO] 1 path(s) to be renamed
[INFO] renamed: 'Keepass\.startup' -> 'Keepass\_startup'
[INFO] 1 path(s) renamed
  • The executable has increased by 459 264 bytes, although there are few changes.
  • The amount of information has grown so much that it simply did not fit on my laptop screen. Why would I need such a detailed explanation of the renaming conditions if I already spent time studying the command line flags in the manual, picked the necessary ones and now I just want the app to fulfill its purpose?
  • The app scared me with a multi-line warning about a new flag, which is enabled by default and should not shout of itself precisely because of being a default one.

This is what I expect to see:

$ brename.exe -S "" -R -p "\.startup" -r "_startup"

brename x.yz by Wei Shen, https://github.com/shenwei356/brename/

[OK] 'Keepass\.gogogo' -> 'Keepass\_gogogo'
1 path(s) renamed

The rest (timestamp, message type, renaming conditions, etc), if at all necessary, should be displayed if a dedicated flag is specified, thereby explicitly asking the app to increase the verbosity of logging.

brename can't find anything to rename

Hi,

i am trying to replace some special characters (: ; ? " \ / < > * |) from folder names on my Synology Diskstation.

Using the command <./brename -d -R -p ":" -r "_" /volume1/my_share> returns "0 path(s) to be renamed". I have tested searching for &,!,?,q,qh ... with the same result. (Searching for returns <[ERRO] illegal regular expression for search pattern: ?>)

Why is brename not working for me? Is i possible to remove the given special characters with brename and how?

The directory tree was created, for testing purposes, with the following script

#!/bin/bash
# Decimal ASCII codes (see man ascii)
ARR=( {32..126} )

# Array count
arrcount=${#ARR[@]}

# return a random string
get_rand_dir(){
    for ((i=1; i<$((RANDOM%30)); i++)) {
        printf \\$(printf '%03o' ${ARR[RANDOM%arrcount]});
    }
}

dir=/volume1/my_share/

# appending random characters to make a hierarchy
for ((i=0; i<$((RANDOM%100)); i++)) {
    dir+="$(get_rand_dir)/"
}

echo $dir
mkdir -p "$dir"

oldir=$(echo "$dir" | cut -d '/' -f1-3)

while [[ $dir ]]; do
    dir=${dir%/*}
    cd $dir
    for ((i=0; i<$((RANDOM%100)); i++)) {
        mkdir &>/dev/null -p $(get_rand_dir)
    }
done

tree "$oldir"

bildschirmfoto 2018-11-17 um 18 19 46

Specify which matches to replace

Hi there. I was playing around with this and i can't find a way to select just the desidered matches only. Let me make some examples about this:

  1. Filename01_description_01

I would like to replace just the first "_" with something else, for example " - " so it will be renamed to

Filename01 - description_01

  1. Filename_02_description_02

I would like to replace just the first two "_" with " - " so it will be renamed to:

Filename - 02 - description_02 and so on.

With regex if you want to match just the first "_" you just remove the /g from the expression but this doesn't work in brename

this command:

brename -p "_" -r " - "

replace all the founds "_" into " - "

Supporting undo renames

  1. Saving renaming details of the LAST successful operation into current path, like .brename_detail.txt.
    1. We may not use \t as the delimiter cause it's legal in path name, _shenwei356-brename_ may better.
  2. Running brename -u to read the file and reverse the renaming.
    1. Warning if the log file not existed.
    2. Reading and reversely renaming.
    3. Removing the log file.

incrementing numbered files/folders

Sometimes, I have a list of files/folders that I've numbered to keep track of order. So I start off with:

001_a
002_b
003_c
004_d

Then I realize that I want to add a new folder between a and b. So now it has to be 001_a, 002_adash, 003_b, 004_c, 005_d.

Is there a pattern I can use to increment the numbers in from folder 002_b onwards?

Similarly, there might be a requirement to decrement the numbers if I delete a folder in between.

Adding parental directory name to file names

Hello!
I'm trying to rename files adding their parent directory name as a prefix, however I can not succeed with brename.

Reproducible example:

mkdir -p Dir1
mkdir -p Dir2

touch Dir1/a.txt
touch Dir1/b.txt

touch Dir2/c.txt
touch Dir2/d.txt
├── Dir1
│   ├── a.txt
│   └── b.txt
└── Dir2
    ├── c.txt
    └── d.txt

I would like to add a name of parantal directory to each file.
The expected result is:

├── Dir1
│   ├── Dir1_a.txt
│   └── Dir1_b.txt
└── Dir2
    ├── Dir2_c.txt
    └── Dir2_d.txt

I've tried the following command, but it doesn't work:

brename \
  -p '(Dir[0-9])' \
  -r '$1/$1_' \
  -R -f '[a-z].txt' \
  -d

On Debian, it could be done with

rename 's/(.*)\//$1\/$1_/' */*

However, this command doesn't work on CentOS because it uses the other rename tool (from util-linux package).

Is it possible to perform this task with brename?

With kind regards,
Vladimir

Natural sort with auto increment

Hi,
I would like to know if it's possible to rename files using natural sort (-N) + auto increment ({nr})?
I've tried the following but it doesn't work as -N seems to work only with -l.

My folder:

$ ls
10.jpg  13.jpg  16.jpg  19.jpg  21.jpg  24.jpg  27.jpg  2.jpg   32.jpg  35.jpg  38.jpg  40.jpg  43.jpg  46.jpg  49.jpg  5.jpg  8.jpg
11.jpg  14.jpg  17.jpg  1.jpg   22.jpg  25.jpg  28.jpg  30.jpg  33.jpg  36.jpg  39.jpg  41.jpg  44.jpg  47.jpg  4.jpg   6.jpg  9.jpg
12.jpg  15.jpg  18.jpg  20.jpg  23.jpg  26.jpg  29.jpg  31.jpg  34.jpg  37.jpg  3.jpg   42.jpg  45.jpg  48.jpg  50.jpg  7.jpg
$ ls -v
1.jpg  4.jpg  7.jpg  10.jpg  13.jpg  16.jpg  19.jpg  22.jpg  25.jpg  28.jpg  31.jpg  34.jpg  37.jpg  40.jpg  43.jpg  46.jpg  49.jpg
2.jpg  5.jpg  8.jpg  11.jpg  14.jpg  17.jpg  20.jpg  23.jpg  26.jpg  29.jpg  32.jpg  35.jpg  38.jpg  41.jpg  44.jpg  47.jpg  50.jpg
3.jpg  6.jpg  9.jpg  12.jpg  15.jpg  18.jpg  21.jpg  24.jpg  27.jpg  30.jpg  33.jpg  36.jpg  39.jpg  42.jpg  45.jpg  48.jpg
$ brename  -p ".*\.jpg" -r "{nr}.jpg" -N --nr-width 3 --start-num 1 -d
Searching for paths to rename...

  [OK] 1.jpg -> 001.jpg
  [OK] 10.jpg -> 002.jpg    // Expecting 2.jpg -> 002.jpg
  [OK] 11.jpg -> 003.jpg
  [OK] 12.jpg -> 004.jpg
  [OK] 13.jpg -> 005.jpg
  [OK] 14.jpg -> 006.jpg
  [OK] 15.jpg -> 007.jpg
  [OK] 16.jpg -> 008.jpg
  [OK] 17.jpg -> 009.jpg
  [OK] 18.jpg -> 010.jpg
  [OK] 19.jpg -> 011.jpg
  [OK] 2.jpg -> 012.jpg
  [OK] 20.jpg -> 013.jpg
...

Here's the result of the command i've used to list matching files using natural sort in my previous folder.

$ brename  -p ".*\.jpg" -l -N
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
10.jpg
11.jpg
12.jpg
...

Thanks!

Homebrew

First off, thank you so much for creating this tool! It's been a super useful introduction to my CLI toolset that has made working with huge numbers of files so much easier.

I was hoping to make this tool installable via Homebrew, macOS's unofficial package manager. There are two ways to create a new entry in Homebrew (as far as I'm aware):

  1. Submit a Formula to homebrew-core that compiles brename from source for macOS. See
    • Pro: This would allow users to run brew install brename.
    • Con: This requires vendoring to be introduced to the project according to the brew audit tool: C: 19: col 7: Do not use `go get`. Please ask upstream to implement Go vendoring
    • Con: This cannot leverage the assets already built and published on GitHub releases.
  2. Create a Tap that users can install from using, e.g., brew install shenwei356/tap/brename (see how croc, another golang project, handles it):
    • Pro: This directly uses the assets stored GitHub releases.
    • Pro: This mandates no changes to the current repository.
    • Con: This usually mandates creating a new repository. However, an approach like pup.rb can be taken where the file is committed directly to this repository and then the user runs a command like brew install https://raw.githubusercontent.com/shenwei356/brename/master/brename.rb which is more bulky).
    • Other: GoReleaser can be used to autogenerate these Formula.

I've made an attempt to author a Formula for both approaches:

homebrew-core Formula

class Brename < Formula
  desc "Safely batch rename files/directories via regular expression"
  homepage "https://github.com/shenwei356/brename"
  url "https://github.com/shenwei356/brename.git",
      tag:      "v2.11.0",
      revision: "c945c33a689b4e79385826db9c828bbf77644e14"
  license "MIT"
  head "https://github.com/shenwei356/brename.git"

  depends_on "go" => :build
  depends_on "gox" => :build

  def install
    ENV["GOPATH"] = buildpath
    dir = buildpath/"src/github.com/shenwei356/brename"
    dir.install buildpath.children

    cd dir do
      system "go", "get", "-v"
      system "gox", "-arch", "amd64", "-os", "darwin", "./..."
      bin.install "brename_darwin_amd64" => "brename"
    end

    prefix.install_metafiles dir
  end

  test do
    # brename normally outputs status information to stderr but shell_output only captures
    # stdout so it must be redirected
    assert_match "checking: \[ ok \]",
      shell_output("#{bin}/brename -p 'zip' -r 'zippy' -d #{test_fixtures("cask")} 2>&1")
  end
end

Tap Formula

class Brename < Formula
  version "2.11.0"
  desc "Safely batch rename files/directories via regular expression"
  homepage "https://github.com/shenwei356/brename"
  license "MIT"
  bottle :unneeded

  if OS.mac?
    if Hardware::CPU.is_64_bit?
      url "https://github.com/shenwei356/brename/releases/download/v2.11.0/brename_darwin_amd64.tar.gz"
      sha256 "7f0094cbaed1154737c716db737404371e7f8e323b09b729455547cd0c75c857"
    else
      url "https://github.com/shenwei356/brename/releases/download/v2.11.0/brename_darwin_386.tar.gz"
      sha256 "1c912a8528247a03a08e44c84974f53c923f3ffa1af4588e4399fa9d3361e060"
    end
  elsif OS.linux?
    if Hardware::CPU.is_64_bit?
      url "https://github.com/shenwei356/brename/releases/download/v2.11.0/brename_linux_amd64.tar.gz"
      sha256 "baf95821def8db827f57995fe2716cac21eddc8215d20c14dfddeb241f03648c"
    else
      url "https://github.com/shenwei356/brename/releases/download/v2.11.0/brename_linux_386.tar.gz"
      sha256 "02606e709bba976d4f80ef2134733e41fc40700b29187330c61dd70108f66d83"
    end
  end

  def install
    bin.install "brename"
  end

  test do
    # brename normally outputs status information to stderr but shell_output only captures
    # stdout so it must be redirected
    assert_match "checking: \[ ok \]",
      shell_output("#{bin}/brename -p 'zip' -r 'zippy' -d #{test_fixtures("cask")} 2>&1")
  end
end

capture and back reference + strings

Thanks for this useful tool.

how to get rid of that space?

## files to change
MMorgan-MelanomaMS3-RNA135-2173_150828-STJ00106-0040-AH3HNTBBXX-1-GTGAAA.star_marked.bam

MMorgan-MelanomaMS3-RNA135-2173_150828-STJ00106-0040-AH3HNTBBXX-1-GTGAAA.star_marked.bam.bai

brename -p "MMorgan.+-([0-9]{4})_.+(bam*)" -r "\$1 stc.\$2" -d

[INFO] checking: [ ok ] 'MMorgan-MelanomaMS3-RNA135-2173_150828-STJ00106-0040-AH3HNTBBXX-1-GTGAAA.star_marked.bam' -> '2173 stc.bam'
[INFO] checking: [ ok ] 'MMorgan-MelanomaMS3-RNA135-2173_150828-STJ00106-0040-AH3HNTBBXX-1-GTGAAA.star_marked.bam.bai' -> '2173 stc.bai'


## not working if no space

brename -p "MMorgan.+-([0-9]{4})_.+(bam*)" -r "\$1stc.\$2" -d
[INFO] checking: [ ok ] 'MMorgan-MelanomaMS3-RNA135-2173_150828-STJ00106-0040-AH3HNTBBXX-1-GTGAAA.star_marked.bam' -> '.bam'
[INFO] checking: [ ok ] 'MMorgan-MelanomaMS3-RNA135-2173_150828-STJ00106-0040-AH3HNTBBXX-1-GTGAAA.star_marked.bam.bai' -> '.bai'

fatal error: runtime: out of memory

The error occurs on Synology DSM 7 x86 often when I scan a folder with bunch of files:

fatal error: runtime: out of memory

runtime stack:
runtime.throw({0x836229?, 0x0?})
/usr/local/go/src/runtime/panic.go:1047 +0x5d fp=0xc00005fdf8 sp=0xc00005fdc8 pc=0x43505d
runtime.sysMapOS(0xc2b1c00000, 0x25c400000?)
/usr/local/go/src/runtime/mem_linux.go:187 +0x11b fp=0xc00005fe40 sp=0xc00005fdf8 pc=0x417e5b
runtime.sysMap(0xb5a400?, 0xc3ffffffff?, 0xb6a598?)
/usr/local/go/src/runtime/mem.go:142 +0x35 fp=0xc00005fe70 sp=0xc00005fe40 pc=0x417835
runtime.(*mheap).grow(0xb5a400, 0x12e1d7?)
/usr/local/go/src/runtime/mheap.go:1522 +0x245 fp=0xc00005fee8 sp=0xc00005fe70 pc=0x427f85
runtime.(*mheap).allocSpan(0xb5a400, 0x12e1d7, 0x0, 0x4f?)
/usr/local/go/src/runtime/mheap.go:1243 +0x1b7 fp=0xc00005ff80 sp=0xc00005fee8 pc=0x4276d7
runtime.(*mheap).alloc.func1()
/usr/local/go/src/runtime/mheap.go:961 +0x65 fp=0xc00005ffc8 sp=0xc00005ff80 pc=0x427185
runtime.systemstack()
/usr/local/go/src/runtime/asm_amd64.s:496 +0x49 fp=0xc00005ffd0 sp=0xc00005ffc8 pc=0x4643e9

goroutine 1 [running]:
runtime.systemstack_switch()
/usr/local/go/src/runtime/asm_amd64.s:463 fp=0xc0001918f0 sp=0xc0001918e8 pc=0x464380
runtime.(*mheap).alloc(0x25c3ae000?, 0x12e1d7?, 0x38?)
/usr/local/go/src/runtime/mheap.go:955 +0x65 fp=0xc000191938 sp=0xc0001918f0 pc=0x4270c5
runtime.(*mcache).allocLarge(0xc00004e400?, 0x25c3add36, 0x1)
/usr/local/go/src/runtime/mcache.go:234 +0x85 fp=0xc000191980 sp=0xc000191938 pc=0x4168c5
runtime.mallocgc(0x25c3add36, 0x7b1da0, 0x1)
/usr/local/go/src/runtime/malloc.go:1053 +0x4f7 fp=0xc0001919e8 sp=0xc000191980 pc=0x40d7d7
runtime.makeslice(0xc05ddee128?, 0x3b?, 0x0?)
/usr/local/go/src/runtime/slice.go:103 +0x52 fp=0xc000191a10 sp=0xc0001919e8 pc=0x44bfb2
os.ReadFile({0x7ffe809a056b?, 0x7ffe809a052e?})
/usr/local/go/src/os/file.go:698 +0xeb fp=0xc000191ae8 sp=0xc000191a10 pc=0x4ef80b
main.walk(0xc000007ba0, 0x4?, {0x7ffe809a056b, 0x3b}, 0x1)
/home/shenwei/go/src/github.com/shenwei356/brename/brename.go:1201 +0x86 fp=0xc000191d70 sp=0xc000191ae8 pc=0x782746
main.glob..func1(0xb3acc0?, {0xc000024600, 0x119, 0x11e})
/home/shenwei/go/src/github.com/shenwei356/brename/brename.go:888 +0x71a fp=0xc00019bd38 sp=0xc000191d70 pc=0x77e95a
github.com/spf13/cobra.(*Command).execute(0xb3acc0, {0xc000023310, 0x11e, 0x12f})
/home/shenwei/go/pkg/mod/github.com/spf13/[email protected]/command.go:920 +0x847 fp=0xc00019be70 sp=0xc00019bd38 pc=0x76c487
github.com/spf13/cobra.(*Command).ExecuteC(0xb3acc0)
/home/shenwei/go/pkg/mod/github.com/spf13/[email protected]/command.go:1044 +0x3bd fp=0xc00019bf28 sp=0xc00019be70 pc=0x76cd1d
github.com/spf13/cobra.(*Command).Execute(...)
/home/shenwei/go/pkg/mod/github.com/spf13/[email protected]/command.go:968
main.main()
/home/shenwei/go/src/github.com/shenwei356/brename/brename.go:557 +0x25 fp=0xc00019bf80 sp=0xc00019bf28 pc=0x77d665
runtime.main()
/usr/local/go/src/runtime/proc.go:250 +0x207 fp=0xc00019bfe0 sp=0xc00019bf80 pc=0x437947
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00019bfe8 sp=0xc00019bfe0 pc=0x466461

goroutine 2 [force gc (idle), 4 minutes]:
runtime.gopark(0x85a767a350f3b?, 0xb401c0?, 0x11?, 0x14?, 0x1?)
/usr/local/go/src/runtime/proc.go:381 +0xd6 fp=0xc00004afb0 sp=0xc00004af90 pc=0x437d76
runtime.goparkunlock(...)
/usr/local/go/src/runtime/proc.go:387
runtime.forcegchelper()
/usr/local/go/src/runtime/proc.go:305 +0xb0 fp=0xc00004afe0 sp=0xc00004afb0 pc=0x437bb0
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004afe8 sp=0xc00004afe0 pc=0x466461
created by runtime.init.6
/usr/local/go/src/runtime/proc.go:293 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x1?, 0x0?, 0x0?, 0x0?, 0x0?)
/usr/local/go/src/runtime/proc.go:381 +0xd6 fp=0xc00004b780 sp=0xc00004b760 pc=0x437d76
runtime.goparkunlock(...)
/usr/local/go/src/runtime/proc.go:387
runtime.bgsweep(0x0?)
/usr/local/go/src/runtime/mgcsweep.go:319 +0xde fp=0xc00004b7c8 sp=0xc00004b780 pc=0x423ffe
runtime.gcenable.func1()
/usr/local/go/src/runtime/mgc.go:178 +0x26 fp=0xc00004b7e0 sp=0xc00004b7c8 pc=0x419286
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004b7e8 sp=0xc00004b7e0 pc=0x466461
created by runtime.gcenable
/usr/local/go/src/runtime/mgc.go:178 +0x6b

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x85a775cea9171?, 0x103776?, 0x0?, 0x0?, 0x0?)
/usr/local/go/src/runtime/proc.go:381 +0xd6 fp=0xc00004bf70 sp=0xc00004bf50 pc=0x437d76
runtime.goparkunlock(...)
/usr/local/go/src/runtime/proc.go:387
runtime.(*scavengerState).park(0xb40d80)
/usr/local/go/src/runtime/mgcscavenge.go:400 +0x53 fp=0xc00004bfa0 sp=0xc00004bf70 pc=0x421ef3
runtime.bgscavenge(0x0?)
/usr/local/go/src/runtime/mgcscavenge.go:633 +0x65 fp=0xc00004bfc8 sp=0xc00004bfa0 pc=0x4224e5
runtime.gcenable.func2()
/usr/local/go/src/runtime/mgc.go:179 +0x26 fp=0xc00004bfe0 sp=0xc00004bfc8 pc=0x419226
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004bfe8 sp=0xc00004bfe0 pc=0x466461
created by runtime.gcenable
/usr/local/go/src/runtime/mgc.go:179 +0xaa

goroutine 5 [finalizer wait, 22 minutes]:
runtime.gopark(0x4380f2?, 0x7f41b3b4aa48?, 0x0?, 0x0?, 0xc00004a770?)
/usr/local/go/src/runtime/proc.go:381 +0xd6 fp=0xc00004a628 sp=0xc00004a608 pc=0x437d76
runtime.runfinq()
/usr/local/go/src/runtime/mfinal.go:193 +0x107 fp=0xc00004a7e0 sp=0xc00004a628 pc=0x4182c7
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004a7e8 sp=0xc00004a7e0 pc=0x466461
created by runtime.createfing
/usr/local/go/src/runtime/mfinal.go:163 +0x45

goroutine 6 [runnable]:
runtime.gcTrigger.test({0x0?, 0x0?, 0x0?})
/usr/local/go/src/runtime/mgc.go:547 +0xfb fp=0xc00008fdd0 sp=0xc00008fdc8 pc=0x41967b
runtime.mallocgc(0x10, 0x7b1ae0, 0x1)
/usr/local/go/src/runtime/malloc.go:1171 +0x768 fp=0xc00008fe38 sp=0xc00008fdd0 pc=0x40da48
runtime.newobject(0xc00007b260?)
/usr/local/go/src/runtime/malloc.go:1254 +0x27 fp=0xc00008fe60 sp=0xc00008fe38 pc=0x40dcc7
main.glob..func1.2()
/home/shenwei/go/src/github.com/shenwei356/brename/brename.go:821 +0x178 fp=0xc00008ffe0 sp=0xc00008fe60 pc=0x77fed8
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00008ffe8 sp=0xc00008ffe0 pc=0x466461
created by main.glob..func1
/home/shenwei/go/src/github.com/shenwei356/brename/brename.go:798 +0x42c

goroutine 7 [GC worker (idle)]:
runtime.gopark(0x8740b8?, 0xc05ddd8000?, 0x1a?, 0x14?, 0x0?)
/usr/local/go/src/runtime/proc.go:381 +0xd6 fp=0xc00004cf50 sp=0xc00004cf30 pc=0x437d76
runtime.gcBgMarkWorker()
/usr/local/go/src/runtime/mgc.go:1275 +0xf1 fp=0xc00004cfe0 sp=0xc00004cf50 pc=0x41aff1
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004cfe8 sp=0xc00004cfe0 pc=0x466461
created by runtime.gcBgMarkStartWorkers
/usr/local/go/src/runtime/mgc.go:1199 +0x25

goroutine 17 [GC worker (idle), 10 minutes]:
runtime.gopark(0x85a01ae1947bf?, 0x3?, 0xc9?, 0x40?, 0x0?)
/usr/local/go/src/runtime/proc.go:381 +0xd6 fp=0xc000046750 sp=0xc000046730 pc=0x437d76
runtime.gcBgMarkWorker()
/usr/local/go/src/runtime/mgc.go:1275 +0xf1 fp=0xc0000467e0 sp=0xc000046750 pc=0x41aff1
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000467e8 sp=0xc0000467e0 pc=0x466461
created by runtime.gcBgMarkStartWorkers
/usr/local/go/src/runtime/mgc.go:1199 +0x25

goroutine 33 [GC worker (idle), 14 minutes]:
runtime.gopark(0xb72240?, 0x3?, 0x93?, 0xd1?, 0x0?)
/usr/local/go/src/runtime/proc.go:381 +0xd6 fp=0xc00004c750 sp=0xc00004c730 pc=0x437d76
runtime.gcBgMarkWorker()
/usr/local/go/src/runtime/mgc.go:1275 +0xf1 fp=0xc00004c7e0 sp=0xc00004c750 pc=0x41aff1
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc00004c7e8 sp=0xc00004c7e0 pc=0x466461
created by runtime.gcBgMarkStartWorkers
/usr/local/go/src/runtime/mgc.go:1199 +0x25

goroutine 18 [GC worker (idle)]:
runtime.gopark(0x85a76dd501994?, 0x3?, 0x8c?, 0x8f?, 0x0?)
/usr/local/go/src/runtime/proc.go:381 +0xd6 fp=0xc000046f50 sp=0xc000046f30 pc=0x437d76
runtime.gcBgMarkWorker()
/usr/local/go/src/runtime/mgc.go:1275 +0xf1 fp=0xc000046fe0 sp=0xc000046f50 pc=0x41aff1
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000046fe8 sp=0xc000046fe0 pc=0x466461
created by runtime.gcBgMarkStartWorkers
/usr/local/go/src/runtime/mgc.go:1199 +0x25

Auto-mkdir

Add a flag that will automatically create necessary directories.

Underscore nullifies/ignored in replacement between matched groups

Hi Shenwei,

Thanks for the awesome. I came across a weird issue. I am trying to replace this pattern:

Input:

1234_OC43_S17_R1.fastq.gz
1234_OC43_S17_R2.fastq.gz
1235_OC43_S24_R1.fastq.gz
...
etc

Expected output:

S17_1234_OC43_R1.fastq.gz
S17_1234_OC43_R2.fastq.gz
S24_1235_OC43_R1.fastq.gz
...
etc

I want to move S\d\d pattern from the middle to the first of the string. eg this: XXX_XXX_S17_R1.fastq.gz becomes S17_XXX_XXX_R1.fastq.gz.

Command I used:

brename -p "(.*)_(S\d+)_(.*)" -r '$2_$1_$3' -d

Output:

  [OK] 1234_OC43_S17_R1.fastq.gz -> R1.fastq.gz
  [OK] 1234_OC43_S17_R2.fastq.gz  -> R2.fastq.gz
  [overwriting newly renamed path] 1235_OC43_S24_R1.fastq.gz -> R1.fastq.gz

Odd! _ seems to completely nullify the group string eg $1

Replacing underscores with - fixes this issue:

brename -p "(.*)_(S\d+)_(.*)" -r '$2-$1-$3' -d

To me the issues seems to be replaced to the regex groups. Because when I run this to achieve the desired result it works:

brename -p "-" -r '_' -d

Thanks!

Versions:

brename v2.14.0
LSB Version:    core-11.1.0ubuntu4-noarch:security-11.1.0ubuntu4-noarch
Distributor ID: Linuxmint
Description:    Linux Mint 21
Release:        21
Codename:       vanessa

Feature Request: Ask user to perform rename on dry run.

Can we ask user to perform rename after a dry run?

$ brename -d -p 386 -r amd64
Searching for paths to rename...

  [OK] brename_linux_386.tar.gz -> brename_linux_amd64.tar.gz
  [OK] brename_windows_386.exe.tar.gz -> brename_windows_amd64.exe.tar.gz

2 path(s) to be renamed, perform rename? [y/N]:

Hit y to rename, n is default so hit enter to dismiss.
So we don't have to re-run another brename command again.

Actually, I think a rename preview like this before renaming should be a default behaviour,
and can be muted with something like -q,--quiet flag.

变量匹配问题

问题格式匹配

(.*) - S(\d+)E(\d+)\.zh_(CN|TW).default.ass$

修改为

$1 - S$2E$3 - 第$3集.zh_$4.default.ass

替换为

brename -p '(.*) - S(\d+)E(\d+)\.zh_(CN|TW).default.ass$' -r '$1 - S$2E$3 - 第$3集.zh_$4.default.ass' -d

图片

预期中间像
S01E11 - 第11集

no match on UTF-8 chars

Tried to rename some french files with UTF-8 chars in it (û) and it seems it does not even match.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.