Home > Blockchain >  Bulk rename files to remove all text before character
Bulk rename files to remove all text before character

Time:01-10

I have a folder with many sub folders nested inside of with images with the name such as "IMG_7729-300x300.jpeg¦IMG_7729-300x300.jpeg". I am trying to find a way using linux to delete all text before the | and including it.

I tried using this but was unable to get it to work

find . -type f -name "*|*" -exec bash -c 'f="$1"; g="${f/*|/}"; mv -- "$f" "$g"' | '{}' \;

CodePudding user response:

Use bash string manipulation and a glob:

touch "IMG_7729-300x300.jpeg¦IMG_7729-300x300.jpeg"
echo "before:"
ls
for fn in *¦*; do
   mv "$fn" "${fn##*¦}"
done

echo "after:"
ls

Try it

If you want to use find this is the best approach:

find . -type f -name "*¦*" -execdir bash -c 'fn="{}"; mv "$fn" "${fn##*¦}"' \;

With the -execdir primary, find executes the command in the directory where the file is found. You don't, therefor, need to deal with the qualifying path before the base filename.

CodePudding user response:

You can use awk to do it simply as well if you lack a POSIX shell (most are). With awk you can simply use '¦' as the field-separator FS and the system command to move the file to a name comprised of the second field only, e.g.

$ls -1 *.jpeg | awk -F¦ '{cmd="mv "$1FS$2" "$2; system(cmd)}' -

Where you simply pipe the output of ls -1 (that's "dash one" not "dash lowercase L"). The cmd is just a string concatenation creating the string mv $1¦$2.jpeg $2.jpeg. (where FS is used for '¦') The system() command simply passes that to the shell. You can adjust the file glob as desired to meet your needs if you have names ending in other than .jpeg, etc.

The result it it would take a directory containing:

$ ls -al
total 24
drwxr-xr-x 3 david david 4096 Jan  9 21:56 .
drwxr-xr-x 6 david david 4096 Nov 18 03:45 ..
drwxr-xr-x 2 david david 4096 Jan  9 21:56 orig
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7721-300x300.jpeg¦IMG_7721-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7722-300x300.jpeg¦IMG_7722-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7723-300x300.jpeg¦IMG_7723-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7724-300x300.jpeg¦IMG_7724-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7725-300x300.jpeg¦IMG_7725-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7726-300x300.jpeg¦IMG_7726-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7727-300x300.jpeg¦IMG_7727-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7728-300x300.jpeg¦IMG_7728-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7729-300x300.jpeg¦IMG_7729-300x300.jpeg
-rw-r--r-- 1 david david  115 Oct 17  2021 f1
-rw-r--r-- 1 david david  117 Oct 17  2021 f2
-rw-r--r-- 1 david david  117 Oct 17  2021 f3

and move the filenames as desire resulting in the contents:

$ ls -al
total 24
drwxr-xr-x 3 david david 4096 Jan  9 22:00 .
drwxr-xr-x 6 david david 4096 Nov 18 03:45 ..
drwxr-xr-x 2 david david 4096 Jan  9 21:56 orig
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7721-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7722-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7723-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7724-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7725-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7726-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7727-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7728-300x300.jpeg
-rw-r--r-- 1 david david    0 Jan  9 21:53 IMG_7729-300x300.jpeg
-rw-r--r-- 1 david david  115 Oct 17  2021 f1
-rw-r--r-- 1 david david  117 Oct 17  2021 f2
-rw-r--r-- 1 david david  117 Oct 17  2021 f3

Note: if you do have bash or shell allowing redirection from a subshell, you can eliminate the pipe using <(ls -1 *.jpeg), e.g.

awk -F¦ '{cmd="mv "$1FS$2" "$2; system(cmd)}' <(ls -1 *.jpeg)

(same result)


Using perl-rename

You can also use perl-rename (often symlinked to rename -- you can check which you have with rename --version). You will either see something like "perl-rename 1.11" or "rename from util-linux 2.38.1")

With perl-rename you can use a simple substitute form s/find/replace/ using extended-REGEX to accomplish the removal of the first part of the filename. In your case that would be:

$ perl-rename 's/^[^¦] ¦//' *.jpeg

Where the find is ^[^¦] ¦:

  • '^' anchored from the beginning of line
  • [^¦] select one-or-more characters not containing a '¦'
  • then select the '¦'

And then replace with (nothing).

That will accomplish the same results as the awk command above. The same caveat applies, adjust the file-glob as needed to operate on the desired files. You can also use the -n option (--just-print, --dry-run) to see what would be renamed first without actually doing to rename to make sure you will accomplish your desired goal.

  • Related