Page 3 of 6 FirstFirst 12345 ... LastLast
Results 21 to 30 of 59

Thread: How to search and replace file name characters

  1. #21
    Join Date
    Jul 2006
    Beans
    Hidden!

    Re: How to search and replace file name characters

    Quote Originally Posted by Vaphell View Post
    wouldn't
    Code:
    s/[∕:.]/-/g
    be cleaner? square brackets are just for that

    i think you need to perform the operation on directories first. When you try to rename files but also change the directory part of its path you are effectively trying to move the file to a place that doesn't exist yet.
    When you rename dirs first, files don't care and then when you rename files, dir part is already set so no problem.
    I see what you're saying.
    So this code only operates on directories?... or how do I exclude the files in the next levels?
    How do I test this and see the output before actually executing?
    Last edited by meanmrmustard; March 19th, 2013 at 03:34 AM.

  2. #22
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,399
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: How to search and replace file name characters

    instead of find -type f try find -type d
    i'll update my post soon with more substance when i whip up some working example.

    can you give an example path broken down to pieces, eg /some/dir/with:troublesome/characters/file.mp3 =
    some
    dir
    with:troublesome
    characters
    file.mp3

    It would be much easier to recreate the situation because trying to figure out which slash is what is not exactly easy on the eyes



    in the charmap there are 2 fancy slashes and i used both in my example. I went with pure bash because i had a regex problem with unexpected char in rename (maybe my version is old or something)
    my test:
    somebandartist (2 different slashes)
    some:album
    file.mp3

    Code:
    $ find -type d
    .
    ./some⁄band∕artist
    ./some⁄band∕artist/some:album
    $ while read -rd $'\0' d; do p=${d%/*}; n=${d##*/}; mv -- "$d" "$p/${n//[⁄∕:]/-}"; done < <( find -depth -type d -iname '*[⁄∕:]*' -print0 ) 
    $ find -type d
    .
    ./some-band-artist
    ./some-band-artist/some-album
    this should get rid of : and weird slashes in directory names. Try on some disposable data first to see if it works.
    Last edited by Vaphell; March 19th, 2013 at 04:59 AM.
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  3. #23
    Join Date
    Jul 2006
    Beans
    Hidden!

    Re: How to search and replace file name characters

    Quote Originally Posted by Vaphell View Post
    instead of find -type f try find -type d
    i'll update my post soon with more substance when i whip up some working example.

    can you give an example path broken down to pieces, eg /some/dir/with:troublesome/characters/file.mp3 =
    some
    dir
    with:troublesome
    characters
    file.mp3

    It would be much easier to recreate the situation because trying to figure out which slash is what is not exactly easy on the eyes
    Are you saying I should execute
    Code:
    /<media/pathtodirectories>/ find -type d -exec rename -vn s/[∕:.]/-/g
    Here is a

    path/dir/dir/file

    which is causing problems:

    media
    newest3TB
    Sun Ra
    Sun Ra - God:Love
    God Is More Than Love Can Ever Be
    01 Days of Happiness.mp3

    Although in this example the track name has no offending characters.
    Here only the colon needs to be changed.
    Last edited by meanmrmustard; March 19th, 2013 at 04:46 AM.

  4. #24
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,399
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: How to search and replace file name characters

    i updated my post even more, either way try running this (but on trash data first so there are no surprises):
    Code:
    while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; mv -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find -depth -iname '*[⁄∕:]*' -print0 )
    this will replace all troublesome chars, from both files and dirs (my earlier post dealt only with dirs but less specific solution should work too).

    Code:
    $ find
    .
    ./some⁄band∕artist
    ./some⁄band∕artist/some:album
    ./some⁄band∕artist/some:album/track:1.mp3
    $ while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; mv -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find -depth -iname '*[⁄∕:]*' -print0 ) 
    $ find
    .
    ./some-band-artist
    ./some-band-artist/some-album
    ./some-band-artist/some-album/track-1.mp3

    i see that you didn't have a problem with slashes at all, i somewhat expected that.
    . at the beginning of the name can be dealt with in similar manner: find ... -name '.*' ... and instead of "$p/${n//.../-}" we can use "$p/-${n#.}"
    Last edited by Vaphell; March 19th, 2013 at 05:18 AM.
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  5. #25
    Join Date
    Jul 2006
    Beans
    Hidden!

    Re: How to search and replace file name characters

    Quote Originally Posted by Vaphell View Post
    i updated my post even more, either way try running this (but on trash data first so there are no surprises):
    Code:
    while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; mv -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find -depth -iname '*[⁄∕:]*' -print0 )

    I fee like I'm trying to read Greek here.
    This should be preceded by the path? In my case "/media/newest3TB" ?
    I have no other data to run it on but the actual files.

    I don't understand how you see no problem with slashes.

    I'm sure there are some slashes within directory and/or file and/or song names that will stop the transfer.


    I'm not even sure what question to as about the code below.
    Is this literally what precedes the "$ while...." line?... and so it will be looking for exactly that format, colons and slashes in only those positions?

    Code:
    $ find
    .
    ./some⁄band∕artist
    ./some⁄band∕artist/some:album
    ./some⁄band∕artist/some:album/track:1.mp3
    $ while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; mv -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find -depth -iname '*[⁄∕:]*' -print0 ) 
    $ find
    .
    ./some-band-artist
    ./some-band-artist/some-album
    ./some-band-artist/some-album/track-1.mp3

    Not sure if it matters but mp3 is not the only format, there's also .flac, .m4a, .shn, etc.
    Last edited by meanmrmustard; March 19th, 2013 at 01:20 PM.

  6. #26
    Join Date
    Jul 2006
    Beans
    Hidden!

    Re: How to search and replace file name characters

    Quote Originally Posted by Vaphell View Post



    in the charmap there are 2 fancy slashes and i used both in my example. I went with pure bash because i had a regex problem with unexpected char in rename (maybe my version is old or something)
    my test:
    somebandartist (2 different slashes)
    some:album
    file.mp3

    Code:
    $ find -type d
    .
    ./some⁄band∕artist
    ./some⁄band∕artist/some:album
    $ while read -rd $'\0' d; do p=${d%/*}; n=${d##*/}; mv -- "$d" "$p/${n//[⁄∕:]/-}"; done < <( find -depth -type d -iname '*[⁄∕:]*' -print0 ) 
    $ find -type d
    .
    ./some-band-artist
    ./some-band-artist/some-album
    this should get rid of : and weird slashes in directory names. Try on some disposable data first to see if it works.
    Doesn't this tell find to search from the root directory?
    I'm also confused about:

    ./some⁄band∕artist
    ./some⁄band∕artist/some:album

    As an example with both characters, and separating dirs in new lines to avoid slash confusion, what I'd expect to find would be more like:

    /Band
    /Artist
    /album Name/Title: susbtitle/yet somemore text

    where slashes behind Title are not the problem ones.

    If I understood exactly what your code is saying I probably wouldn't be so confused.

    Since I have no other data to test this, is there no way to run it non-destructively?

  7. #27
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,399
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: How to search and replace file name characters

    find by default works with current directory (.) and i worked on my example from its root dir, hence ./<things> format. I created just 1 file for test purposes and the code doesn't care about that either way.

    in your case you either need to cd to the proper directory first
    Code:
    cd /media/newest3TB
    find .
    Code:
    cd /media/newest3TB
    while read ...; do ....; done < <( find .  .... )
    or give path directly to find
    Code:
    find /media/newest3TB
    Code:
    while read ...; do ....; done < <( find /media/newest3TB  .... )
    if you run these find . / find <dir> you will see what is the difference (find prepends everything with the path supplied, so find . returns ./<things> but find /media/newest3TB will return a bunch of /media/newest3TB/<things> - both are equally good for the code below assuming you are in the right directory where . and /media/newest3TB are the same location



    Code:
    while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; mv -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find "/media/newest3TB" -depth -iname '*[⁄∕:]*' -print0 )
    splitting that oneliner to a tidier multiline, script ready form looks like this:
    Code:
    while read -rd $'\0' fd             # read paths listed by find one by one
    do
      p=${fd%/*}                        # dir that owns $fd (everything but the last part of path)
      n=${fd##*/}                       # name of $fd (the last part of path)
      mv -- "$fd" "$p/${n//[⁄∕:]/-}"    # rename (change $n)
    done < <( find "/media/newest3TB" -depth -iname '*[⁄∕:]*' -print0 )
    this thing catches the find output (list of everything that has slashes or : in its name, starting from the deepest levels)
    while read combo reads the list one path by one, puts current item in fd variable, fd path gets cut to p (path/dir where fd is located) and n (name) and then it's renamed with mv to p/(n with chars replaced by -). Doing it only on the last parts of the whole paths depth first avoids the problem of moving objects to places that don't exist.

    as i said, make some dir with trash data and check if it works there first (tweak the line by setting proper dir in find)
    you can also put echo before mv so you get a printout of "mv --- oldpath oldpathwithnewname" that would have been executed (no renaming taking place, last part of the path should change to -'s in place of /: )
    Last edited by Vaphell; March 19th, 2013 at 02:53 PM.
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  8. #28
    Join Date
    Jul 2006
    Beans
    Hidden!

    Re: How to search and replace file name characters

    Ahhh! I think I see.
    I appreciate the explanation for how the code works.

    So what I've done is mkdir "0 test" inside newest3TB and place one album whose title needs fixing in it...

    JON ANDERSON -Lord Of The Rings: The Unreleased Yes Songs -[no label 1CD]

    After cding to that dir I ran:
    Code:
    while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; mv -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find "/media/newest3TB/0 test" -depth -iname '*[⁄∕:]*' -print0 )
    the result:
    Code:
    /media/newest3TB/0 test$ while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; mv -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find "/media/newest3TB/0 test" -depth -iname '*[⁄∕:]*' -print0 )
    mv: cannot move `/media/newest3TB/0 test/JON ANDERSON -Lord Of The Rings: The Unreleased Yes Songs -[no label 1CD]' to a subdirectory of itself, `/media/newest3TB/0 test/JON ANDERSON -Lord Of The Rings: The Unreleased Yes Songs -[no label 1CD]/JON ANDERSON -Lord Of The Rings: The Unreleased Yes Songs -[no label 1CD]'
    I think I didn't need to add "/0 test" to the code?


    BTW, is this Perl, Python, something else or simply bash scripting?
    Last edited by meanmrmustard; March 19th, 2013 at 04:13 PM.

  9. #29
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,399
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: How to search and replace file name characters

    interesting, somehow part of the path gets duplicated. I'll investigate that.

    find is recursive so if you didn't add '0 test' to the /media/newest3TB path everything under /media/newest3TB would get tested (all of your stuff).
    if your test data is in some specific dir and that's all that is meant to be tested you have to point exactly there. Being too broad might have disastrous effects if there is some bug, especially with commands like rm, which are irreversible and require recovery software.

    the loop itself is pure bash

    generally you can use while read like this:
    Code:
    while read ...; do ...; done < file
    while read ...; do ...; done < <( command )
    while read ...; do ...; done <<< "string"
    what the 'line' is is decided by read -d. By default delimiter is set to newline but in my code null-char is used to separate the results (both in find -print0 and read -d $'\0') because newline is a legit character that can be used in names in linux filesystems, using \n to delimit results would butcher such weirdo paths.



    edit:
    what happens when you add -T parameter to mv?
    Code:
    mv -T -- ....
    to get more info about the variables you can add debugging stuff, eg echo
    Code:
    while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; echo "p: '$p'"; echo "n: '$n'"; echo "n2: '${n//[⁄∕:]/-}'"; mv -T -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find "/media/newest3TB/0 test" -depth -iname '*[⁄∕:]*' -print0 )
    this will print the values of temporary p, n variables which are used to determine new path. If something goes wrong there, printing these out should indicate if the problem is with them or with the mv itself.

    the code became somewhat unwieldy, you can think about putting it in script, tidily cut to separate lines as shown earlier. Editing it and/or commenting things out with # (eg mv to only see the temporary values to check if they calculate properly) would become much easier.

    Code:
    #!/bin/bash
    
    while read -rd $'\0' fd
    do
      p=${fd%/*}
      n=${fd##*/}
      echo "p: '$p'"
      echo "n: '$n'"
      echo "n2: '${n//[⁄∕:]/-}'"
      mv -T -- "$fd" "$p/${n//[⁄∕:]/-}"
    done < <( find "/media/newest3TB/0 test" -depth -iname '*[⁄∕:]*' -print0 )
    Code:
    chmod +x myscript.sh     # make the file executable
    ./myscript.sh   # run the script
    Last edited by Vaphell; March 19th, 2013 at 05:19 PM.
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  10. #30
    Join Date
    Jul 2006
    Beans
    Hidden!

    Re: How to search and replace file name characters

    Quote Originally Posted by Vaphell View Post
    edit:
    what happens when you add -T parameter to mv?
    Code:
    mv -T -- ....
    Here's the command and result:
    Code:
    /media/newest3TB/0 test$ while read -rd $'\0' fd; do p=${fd%/*}; n=${fd##*/}; echo mv -T -- "$fd" "$p/${n//[⁄∕:]/-}"; done < <( find "/media/newest3TB/0 test" -depth -iname '*[⁄∕:]*' -print0 )
    mv -T -- /media/newest3TB/0 test/JON ANDERSON -Lord Of The Rings: The Unreleased Yes Songs -[no label 1CD] /media/newest3TB/0 test/JON ANDERSON -Lord Of The Rings: The Unreleased Yes Songs -[no label 1CD]
    curt@Cocobolo:/media/newest3TB/0 test$

    Looking in the 0 test dir, the colon is still there.

    I'm still digesting the rest of you post.

Page 3 of 6 FirstFirst 12345 ... LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •