Use FIND with MV to rename files. Delete the found string then prepending it to the filename?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












0















find . -type f -name '*authors-name-string*' -exec bash -c 'mv "$0" "$0/authors-name-string/"' ;


I am trying to rename files nested in several layers of directories that contain an author's name text string embedded somewhat randomly in the filename. Creating a new filename that starts with the author's name followed by the rest of the original filename ... but sans the authors name string that was located in a somewhat random location in the original filename.



The shell command line above will recursively remove the authors-name-text string from the filename, but I have not figured out how to do that AND prepend the authors-name-text (and a trailing "_" underscore) to the start of the filename. Basically I want to move the authors-name-text from wherever it is currently in the filename to being at the beginning of the filename (plus an underscore). As far as I can tell the bash version invoked is v4.3 on my Synology NAS. I've logged in via ssh from my MacBook.



Trying to take thousands of files in different directories organized by subject directory name so that some of the files written by the same author inside the directories appear grouped together when viewing a simple directory listing.



find . -type f -name '*authors-name-string*' -exec bash -c 'mv "$0" "authors-name-string_$0/authors-name-string/"' ;


The above command line fails when it tries to insert the "authors-name-string_" at the front of the entire filename pathway. Since there isn't a starting directory by that name the MV command complains, though, it does still remove the author-name-string from it's original location in the filename as desired.










share|improve this question
























  • Does your system's find command provide an -execdir option?

    – steeldriver
    Feb 19 at 13:09











  • @Mark-in-Settle - can you please paste a sample input file name and an sample output file for better understanding.

    – upkar
    Feb 21 at 10:53















0















find . -type f -name '*authors-name-string*' -exec bash -c 'mv "$0" "$0/authors-name-string/"' ;


I am trying to rename files nested in several layers of directories that contain an author's name text string embedded somewhat randomly in the filename. Creating a new filename that starts with the author's name followed by the rest of the original filename ... but sans the authors name string that was located in a somewhat random location in the original filename.



The shell command line above will recursively remove the authors-name-text string from the filename, but I have not figured out how to do that AND prepend the authors-name-text (and a trailing "_" underscore) to the start of the filename. Basically I want to move the authors-name-text from wherever it is currently in the filename to being at the beginning of the filename (plus an underscore). As far as I can tell the bash version invoked is v4.3 on my Synology NAS. I've logged in via ssh from my MacBook.



Trying to take thousands of files in different directories organized by subject directory name so that some of the files written by the same author inside the directories appear grouped together when viewing a simple directory listing.



find . -type f -name '*authors-name-string*' -exec bash -c 'mv "$0" "authors-name-string_$0/authors-name-string/"' ;


The above command line fails when it tries to insert the "authors-name-string_" at the front of the entire filename pathway. Since there isn't a starting directory by that name the MV command complains, though, it does still remove the author-name-string from it's original location in the filename as desired.










share|improve this question
























  • Does your system's find command provide an -execdir option?

    – steeldriver
    Feb 19 at 13:09











  • @Mark-in-Settle - can you please paste a sample input file name and an sample output file for better understanding.

    – upkar
    Feb 21 at 10:53













0












0








0








find . -type f -name '*authors-name-string*' -exec bash -c 'mv "$0" "$0/authors-name-string/"' ;


I am trying to rename files nested in several layers of directories that contain an author's name text string embedded somewhat randomly in the filename. Creating a new filename that starts with the author's name followed by the rest of the original filename ... but sans the authors name string that was located in a somewhat random location in the original filename.



The shell command line above will recursively remove the authors-name-text string from the filename, but I have not figured out how to do that AND prepend the authors-name-text (and a trailing "_" underscore) to the start of the filename. Basically I want to move the authors-name-text from wherever it is currently in the filename to being at the beginning of the filename (plus an underscore). As far as I can tell the bash version invoked is v4.3 on my Synology NAS. I've logged in via ssh from my MacBook.



Trying to take thousands of files in different directories organized by subject directory name so that some of the files written by the same author inside the directories appear grouped together when viewing a simple directory listing.



find . -type f -name '*authors-name-string*' -exec bash -c 'mv "$0" "authors-name-string_$0/authors-name-string/"' ;


The above command line fails when it tries to insert the "authors-name-string_" at the front of the entire filename pathway. Since there isn't a starting directory by that name the MV command complains, though, it does still remove the author-name-string from it's original location in the filename as desired.










share|improve this question
















find . -type f -name '*authors-name-string*' -exec bash -c 'mv "$0" "$0/authors-name-string/"' ;


I am trying to rename files nested in several layers of directories that contain an author's name text string embedded somewhat randomly in the filename. Creating a new filename that starts with the author's name followed by the rest of the original filename ... but sans the authors name string that was located in a somewhat random location in the original filename.



The shell command line above will recursively remove the authors-name-text string from the filename, but I have not figured out how to do that AND prepend the authors-name-text (and a trailing "_" underscore) to the start of the filename. Basically I want to move the authors-name-text from wherever it is currently in the filename to being at the beginning of the filename (plus an underscore). As far as I can tell the bash version invoked is v4.3 on my Synology NAS. I've logged in via ssh from my MacBook.



Trying to take thousands of files in different directories organized by subject directory name so that some of the files written by the same author inside the directories appear grouped together when viewing a simple directory listing.



find . -type f -name '*authors-name-string*' -exec bash -c 'mv "$0" "authors-name-string_$0/authors-name-string/"' ;


The above command line fails when it tries to insert the "authors-name-string_" at the front of the entire filename pathway. Since there isn't a starting directory by that name the MV command complains, though, it does still remove the author-name-string from it's original location in the filename as desired.







shell find regular-expression rename mv






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 19 at 22:21









Rui F Ribeiro

41.5k1483140




41.5k1483140










asked Feb 19 at 11:54









Mark-in-SeattleMark-in-Seattle

82




82












  • Does your system's find command provide an -execdir option?

    – steeldriver
    Feb 19 at 13:09











  • @Mark-in-Settle - can you please paste a sample input file name and an sample output file for better understanding.

    – upkar
    Feb 21 at 10:53

















  • Does your system's find command provide an -execdir option?

    – steeldriver
    Feb 19 at 13:09











  • @Mark-in-Settle - can you please paste a sample input file name and an sample output file for better understanding.

    – upkar
    Feb 21 at 10:53
















Does your system's find command provide an -execdir option?

– steeldriver
Feb 19 at 13:09





Does your system's find command provide an -execdir option?

– steeldriver
Feb 19 at 13:09













@Mark-in-Settle - can you please paste a sample input file name and an sample output file for better understanding.

– upkar
Feb 21 at 10:53





@Mark-in-Settle - can you please paste a sample input file name and an sample output file for better understanding.

– upkar
Feb 21 at 10:53










2 Answers
2






active

oldest

votes


















0
















Expanding on your approach and leveraging parameter expansion:



export author_string='author1'
export new_string='author1'
find . -type f -name "*$author_string*"
-exec sh -c '
path="$1%/*"
tmp="$1%%$author_string[^/]*"
before="$tmp##*/"
after="$1##*$author_string"
echo mv -- "$1" "$path/$new_string_$before$after"' sh ;


My assumptions, since I'm not sure I completely understand your question:



You are searching for files whose name contains a fixed string; here, the variable author_string.

You are renaming files everywhere in a directory tree.

The new name of your files will start with a fixed string (it being the same as author_string or not, makes no big difference); here, the variable new_string.

The remainder of the new name of your files will be equal to their old name, except for the author_string part, which you want removed.



In this code:



  • We export our old/new strings to make them available to the shell invoked by find.

  • With an eye on portability, -exec calls sh. $1 is used instead of $0, as in your snippets, because $0 is typically used to set the name of the shell/command.

  • For each file, we split its full path:


    • path="$1%/*" is the full path with the file name part removed: $parameter%word removes a suffix that matches the word pattern;


    • tmp="$1%%$author_string[^/]*" catches the part of each file's full path that precedes author_string: $parameter%%word removes the longest suffix that matches the word pattern. We use [^/] to ignore any occurrence of author_string as part of directory names;


    • before="$tmp##*/" captures only the substring that is part of the file name: $parameter##word removes the longest prefix that matches the word pattern;


    • after="$1##*$author_string" is the part of the file name that comes after author_string;


  • We rename each file.

Note that, if author_string is repeated in a file name, anything in between the occurrences is lost.



Also, bear in mind that you will need to escape (with a ) all the characters in author_string that have a special pattern matching meaning, if you want to match them literally.



Given the directory tree:



$ tree .
.
├── testdir
│   ├── title2_author1_date.book
│   ├── title3_author1_date.book
│   └── title4_author2_date.book
├── title1_author1_date.book
└── title5_author2_date.book


This code does:



$ export author_string='author1' new_string='author1'; find . -type f -name "*$author_string*" -exec sh -c 'path="$1%/*"; tmp="$1%%$author_string[^/]*"; before="$tmp##*/"; after="$1##*$author_string"; echo mv -- "$1" "$path/$new_string_$before$after"' sh ;
mv -- ./title1_author1_date.book ./author1_title1__date.book
mv -- ./testdir/title3_author1_date.book ./testdir/author1_title3__date.book
mv -- ./testdir/title2_author1_date.book ./testdir/author1_title2__date.book


Remove echo from the command when you feel you are ready to actually rename files.




References:



Parameter Expansion in "The Open Group Base Specifications Issue 7, 2018 edition" (POSIX.1-2017)






share|improve this answer

























  • Thank you very very much. After some time spend learning from your approach to the problem and your code, then testing on samples and finally using your code on my target directory structure I can say it worked very well indeed and saved many hours. There were only a few minor rename quirks involving a very small number of files. The issue involved unanticipated residual "_" underscore characters in the new filename. Because you gave me a better understanding of shell commands I have the confidence to learn more and adjust the code to handle these few special cases.

    – Mark-in-Seattle
    Feb 20 at 9:55











  • For the benefit of anyone wanting to use fra-san's answer, the tiny number of "unanticipated residual _ underscore quirks in the filenames were entirely of my own making in the original filename choices and cosmetic. The code did not insert any incorrectly. Example: a few filenames used the author-name-string preceded by an _ at the end of the filename, so when the shell script moved author-name to the front of the new filename successfully, I had not thought in that case it would leave a dangling _ underscore which looked odd. So I will code for those few special cosmetic cases.

    – Mark-in-Seattle
    Feb 20 at 10:25












  • Small Update -- when I tried using the shell command line on one of my smaller Synology NAS it did not work. Testing revealed that particular shell was including the apostrophe ‘ characters used in the export author_string=‘author1’ ; export new_string='author1' commands. When I substituted export author_string=“author1” with “ double quote marks corrected the problem, so that echo $author_string => author1 resulted in only the author1 string without quotemarks.

    – Mark-in-Seattle
    Feb 21 at 1:40












  • @Mark-in-Seattle Probably a copy/paste issue: the single quote character accepted by the shell is ASCII 39 (hexadecimal: 27), as are those in new_string='author1'. The quotes in the author_string=‘author1’ string you pasted are U+2018 (hexadecimal: e2 80 98) and U+2019 (hexadecimal: e2 80 98) and they probably come from some text editor.

    – fra-san
    Feb 21 at 7:11



















0














Sounds like a job for Larry Wall's rename. Beware there are other commands with the same name, this one is written in purl.






share|improve this answer






















    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f501572%2fuse-find-with-mv-to-rename-files-delete-the-found-string-then-prepending-it-to%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0
















    Expanding on your approach and leveraging parameter expansion:



    export author_string='author1'
    export new_string='author1'
    find . -type f -name "*$author_string*"
    -exec sh -c '
    path="$1%/*"
    tmp="$1%%$author_string[^/]*"
    before="$tmp##*/"
    after="$1##*$author_string"
    echo mv -- "$1" "$path/$new_string_$before$after"' sh ;


    My assumptions, since I'm not sure I completely understand your question:



    You are searching for files whose name contains a fixed string; here, the variable author_string.

    You are renaming files everywhere in a directory tree.

    The new name of your files will start with a fixed string (it being the same as author_string or not, makes no big difference); here, the variable new_string.

    The remainder of the new name of your files will be equal to their old name, except for the author_string part, which you want removed.



    In this code:



    • We export our old/new strings to make them available to the shell invoked by find.

    • With an eye on portability, -exec calls sh. $1 is used instead of $0, as in your snippets, because $0 is typically used to set the name of the shell/command.

    • For each file, we split its full path:


      • path="$1%/*" is the full path with the file name part removed: $parameter%word removes a suffix that matches the word pattern;


      • tmp="$1%%$author_string[^/]*" catches the part of each file's full path that precedes author_string: $parameter%%word removes the longest suffix that matches the word pattern. We use [^/] to ignore any occurrence of author_string as part of directory names;


      • before="$tmp##*/" captures only the substring that is part of the file name: $parameter##word removes the longest prefix that matches the word pattern;


      • after="$1##*$author_string" is the part of the file name that comes after author_string;


    • We rename each file.

    Note that, if author_string is repeated in a file name, anything in between the occurrences is lost.



    Also, bear in mind that you will need to escape (with a ) all the characters in author_string that have a special pattern matching meaning, if you want to match them literally.



    Given the directory tree:



    $ tree .
    .
    ├── testdir
    │   ├── title2_author1_date.book
    │   ├── title3_author1_date.book
    │   └── title4_author2_date.book
    ├── title1_author1_date.book
    └── title5_author2_date.book


    This code does:



    $ export author_string='author1' new_string='author1'; find . -type f -name "*$author_string*" -exec sh -c 'path="$1%/*"; tmp="$1%%$author_string[^/]*"; before="$tmp##*/"; after="$1##*$author_string"; echo mv -- "$1" "$path/$new_string_$before$after"' sh ;
    mv -- ./title1_author1_date.book ./author1_title1__date.book
    mv -- ./testdir/title3_author1_date.book ./testdir/author1_title3__date.book
    mv -- ./testdir/title2_author1_date.book ./testdir/author1_title2__date.book


    Remove echo from the command when you feel you are ready to actually rename files.




    References:



    Parameter Expansion in "The Open Group Base Specifications Issue 7, 2018 edition" (POSIX.1-2017)






    share|improve this answer

























    • Thank you very very much. After some time spend learning from your approach to the problem and your code, then testing on samples and finally using your code on my target directory structure I can say it worked very well indeed and saved many hours. There were only a few minor rename quirks involving a very small number of files. The issue involved unanticipated residual "_" underscore characters in the new filename. Because you gave me a better understanding of shell commands I have the confidence to learn more and adjust the code to handle these few special cases.

      – Mark-in-Seattle
      Feb 20 at 9:55











    • For the benefit of anyone wanting to use fra-san's answer, the tiny number of "unanticipated residual _ underscore quirks in the filenames were entirely of my own making in the original filename choices and cosmetic. The code did not insert any incorrectly. Example: a few filenames used the author-name-string preceded by an _ at the end of the filename, so when the shell script moved author-name to the front of the new filename successfully, I had not thought in that case it would leave a dangling _ underscore which looked odd. So I will code for those few special cosmetic cases.

      – Mark-in-Seattle
      Feb 20 at 10:25












    • Small Update -- when I tried using the shell command line on one of my smaller Synology NAS it did not work. Testing revealed that particular shell was including the apostrophe ‘ characters used in the export author_string=‘author1’ ; export new_string='author1' commands. When I substituted export author_string=“author1” with “ double quote marks corrected the problem, so that echo $author_string => author1 resulted in only the author1 string without quotemarks.

      – Mark-in-Seattle
      Feb 21 at 1:40












    • @Mark-in-Seattle Probably a copy/paste issue: the single quote character accepted by the shell is ASCII 39 (hexadecimal: 27), as are those in new_string='author1'. The quotes in the author_string=‘author1’ string you pasted are U+2018 (hexadecimal: e2 80 98) and U+2019 (hexadecimal: e2 80 98) and they probably come from some text editor.

      – fra-san
      Feb 21 at 7:11
















    0
















    Expanding on your approach and leveraging parameter expansion:



    export author_string='author1'
    export new_string='author1'
    find . -type f -name "*$author_string*"
    -exec sh -c '
    path="$1%/*"
    tmp="$1%%$author_string[^/]*"
    before="$tmp##*/"
    after="$1##*$author_string"
    echo mv -- "$1" "$path/$new_string_$before$after"' sh ;


    My assumptions, since I'm not sure I completely understand your question:



    You are searching for files whose name contains a fixed string; here, the variable author_string.

    You are renaming files everywhere in a directory tree.

    The new name of your files will start with a fixed string (it being the same as author_string or not, makes no big difference); here, the variable new_string.

    The remainder of the new name of your files will be equal to their old name, except for the author_string part, which you want removed.



    In this code:



    • We export our old/new strings to make them available to the shell invoked by find.

    • With an eye on portability, -exec calls sh. $1 is used instead of $0, as in your snippets, because $0 is typically used to set the name of the shell/command.

    • For each file, we split its full path:


      • path="$1%/*" is the full path with the file name part removed: $parameter%word removes a suffix that matches the word pattern;


      • tmp="$1%%$author_string[^/]*" catches the part of each file's full path that precedes author_string: $parameter%%word removes the longest suffix that matches the word pattern. We use [^/] to ignore any occurrence of author_string as part of directory names;


      • before="$tmp##*/" captures only the substring that is part of the file name: $parameter##word removes the longest prefix that matches the word pattern;


      • after="$1##*$author_string" is the part of the file name that comes after author_string;


    • We rename each file.

    Note that, if author_string is repeated in a file name, anything in between the occurrences is lost.



    Also, bear in mind that you will need to escape (with a ) all the characters in author_string that have a special pattern matching meaning, if you want to match them literally.



    Given the directory tree:



    $ tree .
    .
    ├── testdir
    │   ├── title2_author1_date.book
    │   ├── title3_author1_date.book
    │   └── title4_author2_date.book
    ├── title1_author1_date.book
    └── title5_author2_date.book


    This code does:



    $ export author_string='author1' new_string='author1'; find . -type f -name "*$author_string*" -exec sh -c 'path="$1%/*"; tmp="$1%%$author_string[^/]*"; before="$tmp##*/"; after="$1##*$author_string"; echo mv -- "$1" "$path/$new_string_$before$after"' sh ;
    mv -- ./title1_author1_date.book ./author1_title1__date.book
    mv -- ./testdir/title3_author1_date.book ./testdir/author1_title3__date.book
    mv -- ./testdir/title2_author1_date.book ./testdir/author1_title2__date.book


    Remove echo from the command when you feel you are ready to actually rename files.




    References:



    Parameter Expansion in "The Open Group Base Specifications Issue 7, 2018 edition" (POSIX.1-2017)






    share|improve this answer

























    • Thank you very very much. After some time spend learning from your approach to the problem and your code, then testing on samples and finally using your code on my target directory structure I can say it worked very well indeed and saved many hours. There were only a few minor rename quirks involving a very small number of files. The issue involved unanticipated residual "_" underscore characters in the new filename. Because you gave me a better understanding of shell commands I have the confidence to learn more and adjust the code to handle these few special cases.

      – Mark-in-Seattle
      Feb 20 at 9:55











    • For the benefit of anyone wanting to use fra-san's answer, the tiny number of "unanticipated residual _ underscore quirks in the filenames were entirely of my own making in the original filename choices and cosmetic. The code did not insert any incorrectly. Example: a few filenames used the author-name-string preceded by an _ at the end of the filename, so when the shell script moved author-name to the front of the new filename successfully, I had not thought in that case it would leave a dangling _ underscore which looked odd. So I will code for those few special cosmetic cases.

      – Mark-in-Seattle
      Feb 20 at 10:25












    • Small Update -- when I tried using the shell command line on one of my smaller Synology NAS it did not work. Testing revealed that particular shell was including the apostrophe ‘ characters used in the export author_string=‘author1’ ; export new_string='author1' commands. When I substituted export author_string=“author1” with “ double quote marks corrected the problem, so that echo $author_string => author1 resulted in only the author1 string without quotemarks.

      – Mark-in-Seattle
      Feb 21 at 1:40












    • @Mark-in-Seattle Probably a copy/paste issue: the single quote character accepted by the shell is ASCII 39 (hexadecimal: 27), as are those in new_string='author1'. The quotes in the author_string=‘author1’ string you pasted are U+2018 (hexadecimal: e2 80 98) and U+2019 (hexadecimal: e2 80 98) and they probably come from some text editor.

      – fra-san
      Feb 21 at 7:11














    0












    0








    0









    Expanding on your approach and leveraging parameter expansion:



    export author_string='author1'
    export new_string='author1'
    find . -type f -name "*$author_string*"
    -exec sh -c '
    path="$1%/*"
    tmp="$1%%$author_string[^/]*"
    before="$tmp##*/"
    after="$1##*$author_string"
    echo mv -- "$1" "$path/$new_string_$before$after"' sh ;


    My assumptions, since I'm not sure I completely understand your question:



    You are searching for files whose name contains a fixed string; here, the variable author_string.

    You are renaming files everywhere in a directory tree.

    The new name of your files will start with a fixed string (it being the same as author_string or not, makes no big difference); here, the variable new_string.

    The remainder of the new name of your files will be equal to their old name, except for the author_string part, which you want removed.



    In this code:



    • We export our old/new strings to make them available to the shell invoked by find.

    • With an eye on portability, -exec calls sh. $1 is used instead of $0, as in your snippets, because $0 is typically used to set the name of the shell/command.

    • For each file, we split its full path:


      • path="$1%/*" is the full path with the file name part removed: $parameter%word removes a suffix that matches the word pattern;


      • tmp="$1%%$author_string[^/]*" catches the part of each file's full path that precedes author_string: $parameter%%word removes the longest suffix that matches the word pattern. We use [^/] to ignore any occurrence of author_string as part of directory names;


      • before="$tmp##*/" captures only the substring that is part of the file name: $parameter##word removes the longest prefix that matches the word pattern;


      • after="$1##*$author_string" is the part of the file name that comes after author_string;


    • We rename each file.

    Note that, if author_string is repeated in a file name, anything in between the occurrences is lost.



    Also, bear in mind that you will need to escape (with a ) all the characters in author_string that have a special pattern matching meaning, if you want to match them literally.



    Given the directory tree:



    $ tree .
    .
    ├── testdir
    │   ├── title2_author1_date.book
    │   ├── title3_author1_date.book
    │   └── title4_author2_date.book
    ├── title1_author1_date.book
    └── title5_author2_date.book


    This code does:



    $ export author_string='author1' new_string='author1'; find . -type f -name "*$author_string*" -exec sh -c 'path="$1%/*"; tmp="$1%%$author_string[^/]*"; before="$tmp##*/"; after="$1##*$author_string"; echo mv -- "$1" "$path/$new_string_$before$after"' sh ;
    mv -- ./title1_author1_date.book ./author1_title1__date.book
    mv -- ./testdir/title3_author1_date.book ./testdir/author1_title3__date.book
    mv -- ./testdir/title2_author1_date.book ./testdir/author1_title2__date.book


    Remove echo from the command when you feel you are ready to actually rename files.




    References:



    Parameter Expansion in "The Open Group Base Specifications Issue 7, 2018 edition" (POSIX.1-2017)






    share|improve this answer

















    Expanding on your approach and leveraging parameter expansion:



    export author_string='author1'
    export new_string='author1'
    find . -type f -name "*$author_string*"
    -exec sh -c '
    path="$1%/*"
    tmp="$1%%$author_string[^/]*"
    before="$tmp##*/"
    after="$1##*$author_string"
    echo mv -- "$1" "$path/$new_string_$before$after"' sh ;


    My assumptions, since I'm not sure I completely understand your question:



    You are searching for files whose name contains a fixed string; here, the variable author_string.

    You are renaming files everywhere in a directory tree.

    The new name of your files will start with a fixed string (it being the same as author_string or not, makes no big difference); here, the variable new_string.

    The remainder of the new name of your files will be equal to their old name, except for the author_string part, which you want removed.



    In this code:



    • We export our old/new strings to make them available to the shell invoked by find.

    • With an eye on portability, -exec calls sh. $1 is used instead of $0, as in your snippets, because $0 is typically used to set the name of the shell/command.

    • For each file, we split its full path:


      • path="$1%/*" is the full path with the file name part removed: $parameter%word removes a suffix that matches the word pattern;


      • tmp="$1%%$author_string[^/]*" catches the part of each file's full path that precedes author_string: $parameter%%word removes the longest suffix that matches the word pattern. We use [^/] to ignore any occurrence of author_string as part of directory names;


      • before="$tmp##*/" captures only the substring that is part of the file name: $parameter##word removes the longest prefix that matches the word pattern;


      • after="$1##*$author_string" is the part of the file name that comes after author_string;


    • We rename each file.

    Note that, if author_string is repeated in a file name, anything in between the occurrences is lost.



    Also, bear in mind that you will need to escape (with a ) all the characters in author_string that have a special pattern matching meaning, if you want to match them literally.



    Given the directory tree:



    $ tree .
    .
    ├── testdir
    │   ├── title2_author1_date.book
    │   ├── title3_author1_date.book
    │   └── title4_author2_date.book
    ├── title1_author1_date.book
    └── title5_author2_date.book


    This code does:



    $ export author_string='author1' new_string='author1'; find . -type f -name "*$author_string*" -exec sh -c 'path="$1%/*"; tmp="$1%%$author_string[^/]*"; before="$tmp##*/"; after="$1##*$author_string"; echo mv -- "$1" "$path/$new_string_$before$after"' sh ;
    mv -- ./title1_author1_date.book ./author1_title1__date.book
    mv -- ./testdir/title3_author1_date.book ./testdir/author1_title3__date.book
    mv -- ./testdir/title2_author1_date.book ./testdir/author1_title2__date.book


    Remove echo from the command when you feel you are ready to actually rename files.




    References:



    Parameter Expansion in "The Open Group Base Specifications Issue 7, 2018 edition" (POSIX.1-2017)







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 21 at 7:11

























    answered Feb 19 at 18:51









    fra-sanfra-san

    1,8511520




    1,8511520












    • Thank you very very much. After some time spend learning from your approach to the problem and your code, then testing on samples and finally using your code on my target directory structure I can say it worked very well indeed and saved many hours. There were only a few minor rename quirks involving a very small number of files. The issue involved unanticipated residual "_" underscore characters in the new filename. Because you gave me a better understanding of shell commands I have the confidence to learn more and adjust the code to handle these few special cases.

      – Mark-in-Seattle
      Feb 20 at 9:55











    • For the benefit of anyone wanting to use fra-san's answer, the tiny number of "unanticipated residual _ underscore quirks in the filenames were entirely of my own making in the original filename choices and cosmetic. The code did not insert any incorrectly. Example: a few filenames used the author-name-string preceded by an _ at the end of the filename, so when the shell script moved author-name to the front of the new filename successfully, I had not thought in that case it would leave a dangling _ underscore which looked odd. So I will code for those few special cosmetic cases.

      – Mark-in-Seattle
      Feb 20 at 10:25












    • Small Update -- when I tried using the shell command line on one of my smaller Synology NAS it did not work. Testing revealed that particular shell was including the apostrophe ‘ characters used in the export author_string=‘author1’ ; export new_string='author1' commands. When I substituted export author_string=“author1” with “ double quote marks corrected the problem, so that echo $author_string => author1 resulted in only the author1 string without quotemarks.

      – Mark-in-Seattle
      Feb 21 at 1:40












    • @Mark-in-Seattle Probably a copy/paste issue: the single quote character accepted by the shell is ASCII 39 (hexadecimal: 27), as are those in new_string='author1'. The quotes in the author_string=‘author1’ string you pasted are U+2018 (hexadecimal: e2 80 98) and U+2019 (hexadecimal: e2 80 98) and they probably come from some text editor.

      – fra-san
      Feb 21 at 7:11


















    • Thank you very very much. After some time spend learning from your approach to the problem and your code, then testing on samples and finally using your code on my target directory structure I can say it worked very well indeed and saved many hours. There were only a few minor rename quirks involving a very small number of files. The issue involved unanticipated residual "_" underscore characters in the new filename. Because you gave me a better understanding of shell commands I have the confidence to learn more and adjust the code to handle these few special cases.

      – Mark-in-Seattle
      Feb 20 at 9:55











    • For the benefit of anyone wanting to use fra-san's answer, the tiny number of "unanticipated residual _ underscore quirks in the filenames were entirely of my own making in the original filename choices and cosmetic. The code did not insert any incorrectly. Example: a few filenames used the author-name-string preceded by an _ at the end of the filename, so when the shell script moved author-name to the front of the new filename successfully, I had not thought in that case it would leave a dangling _ underscore which looked odd. So I will code for those few special cosmetic cases.

      – Mark-in-Seattle
      Feb 20 at 10:25












    • Small Update -- when I tried using the shell command line on one of my smaller Synology NAS it did not work. Testing revealed that particular shell was including the apostrophe ‘ characters used in the export author_string=‘author1’ ; export new_string='author1' commands. When I substituted export author_string=“author1” with “ double quote marks corrected the problem, so that echo $author_string => author1 resulted in only the author1 string without quotemarks.

      – Mark-in-Seattle
      Feb 21 at 1:40












    • @Mark-in-Seattle Probably a copy/paste issue: the single quote character accepted by the shell is ASCII 39 (hexadecimal: 27), as are those in new_string='author1'. The quotes in the author_string=‘author1’ string you pasted are U+2018 (hexadecimal: e2 80 98) and U+2019 (hexadecimal: e2 80 98) and they probably come from some text editor.

      – fra-san
      Feb 21 at 7:11

















    Thank you very very much. After some time spend learning from your approach to the problem and your code, then testing on samples and finally using your code on my target directory structure I can say it worked very well indeed and saved many hours. There were only a few minor rename quirks involving a very small number of files. The issue involved unanticipated residual "_" underscore characters in the new filename. Because you gave me a better understanding of shell commands I have the confidence to learn more and adjust the code to handle these few special cases.

    – Mark-in-Seattle
    Feb 20 at 9:55





    Thank you very very much. After some time spend learning from your approach to the problem and your code, then testing on samples and finally using your code on my target directory structure I can say it worked very well indeed and saved many hours. There were only a few minor rename quirks involving a very small number of files. The issue involved unanticipated residual "_" underscore characters in the new filename. Because you gave me a better understanding of shell commands I have the confidence to learn more and adjust the code to handle these few special cases.

    – Mark-in-Seattle
    Feb 20 at 9:55













    For the benefit of anyone wanting to use fra-san's answer, the tiny number of "unanticipated residual _ underscore quirks in the filenames were entirely of my own making in the original filename choices and cosmetic. The code did not insert any incorrectly. Example: a few filenames used the author-name-string preceded by an _ at the end of the filename, so when the shell script moved author-name to the front of the new filename successfully, I had not thought in that case it would leave a dangling _ underscore which looked odd. So I will code for those few special cosmetic cases.

    – Mark-in-Seattle
    Feb 20 at 10:25






    For the benefit of anyone wanting to use fra-san's answer, the tiny number of "unanticipated residual _ underscore quirks in the filenames were entirely of my own making in the original filename choices and cosmetic. The code did not insert any incorrectly. Example: a few filenames used the author-name-string preceded by an _ at the end of the filename, so when the shell script moved author-name to the front of the new filename successfully, I had not thought in that case it would leave a dangling _ underscore which looked odd. So I will code for those few special cosmetic cases.

    – Mark-in-Seattle
    Feb 20 at 10:25














    Small Update -- when I tried using the shell command line on one of my smaller Synology NAS it did not work. Testing revealed that particular shell was including the apostrophe ‘ characters used in the export author_string=‘author1’ ; export new_string='author1' commands. When I substituted export author_string=“author1” with “ double quote marks corrected the problem, so that echo $author_string => author1 resulted in only the author1 string without quotemarks.

    – Mark-in-Seattle
    Feb 21 at 1:40






    Small Update -- when I tried using the shell command line on one of my smaller Synology NAS it did not work. Testing revealed that particular shell was including the apostrophe ‘ characters used in the export author_string=‘author1’ ; export new_string='author1' commands. When I substituted export author_string=“author1” with “ double quote marks corrected the problem, so that echo $author_string => author1 resulted in only the author1 string without quotemarks.

    – Mark-in-Seattle
    Feb 21 at 1:40














    @Mark-in-Seattle Probably a copy/paste issue: the single quote character accepted by the shell is ASCII 39 (hexadecimal: 27), as are those in new_string='author1'. The quotes in the author_string=‘author1’ string you pasted are U+2018 (hexadecimal: e2 80 98) and U+2019 (hexadecimal: e2 80 98) and they probably come from some text editor.

    – fra-san
    Feb 21 at 7:11






    @Mark-in-Seattle Probably a copy/paste issue: the single quote character accepted by the shell is ASCII 39 (hexadecimal: 27), as are those in new_string='author1'. The quotes in the author_string=‘author1’ string you pasted are U+2018 (hexadecimal: e2 80 98) and U+2019 (hexadecimal: e2 80 98) and they probably come from some text editor.

    – fra-san
    Feb 21 at 7:11














    0














    Sounds like a job for Larry Wall's rename. Beware there are other commands with the same name, this one is written in purl.






    share|improve this answer



























      0














      Sounds like a job for Larry Wall's rename. Beware there are other commands with the same name, this one is written in purl.






      share|improve this answer

























        0












        0








        0







        Sounds like a job for Larry Wall's rename. Beware there are other commands with the same name, this one is written in purl.






        share|improve this answer













        Sounds like a job for Larry Wall's rename. Beware there are other commands with the same name, this one is written in purl.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Feb 19 at 12:40









        ctrl-alt-delorctrl-alt-delor

        12k42360




        12k42360



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f501572%2fuse-find-with-mv-to-rename-files-delete-the-found-string-then-prepending-it-to%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown






            Popular posts from this blog

            Peggy Mitchell

            Palaiologos

            The Forum (Inglewood, California)