Find files recursively and rename based on their full path

隐身守侯 提交于 2021-01-29 09:52:17

问题


I'm looking to search for files of a specific name, modify the name to the full path and then copy the results to another folder.

Is it possible to update each find result with the full path as the file name; i.e.

./folder/subfolder/my-file.csv

becomes

folder_subfolder_my-file.csv

I am listing the files using the following and would like to script it.

find . -name my-file.csv -exec ls {} \;

回答1:


Since you're using bash, you can take advantage of globstar and use a for loop:

shopt -s globstar # set globstar option
for csv in **/my-file.csv; do
  echo "$csv" "${csv//\//_}"
done

shopt -u globstar # unset the option if you don't want it any more

With globstar enabled, ** does a recursive search (similar to the basic functionality of find).

"${csv//\//_}" is an example of ${var//match/replace}, which does a global replacement of all instances of match (here an escaped /) with replace.

If you're happy with the output, then change the echo to mv.




回答2:


Just to demonstrate how to do this with find;

find . -type f -exec bash -c '
    for file; do
        f=${file#./}
        cp "$file" "./${f//\//_}"
    done' _ {} +

The Bash pattern expansion ${f//x/y} replaces x with y throughout. Because find prefixes each found file with the path where it was found (here, ./) we trim that off in order to avoid doing mv "./file" "._file". And because the slash is used in the parameter expansion itself, we need to backslash the slash we want the shell to interpret literally. Finally, because this parameter expansion syntax is a Bash-only extension, we use bash rather than sh.

Obviously, if you want to rename rather than copy, replace cp with mv.

If your find does not support -exec ... + this needs to be refactored somewhat (probably to use xargs); but it should be supported on any reasonably modern platform.




回答3:


With perl's rename command ...

$ prename
Usage: rename [-v] [-n] [-f] perlexpr [filenames]

... you can rename multiple files by applying a regular expression. rename also accepts file names via stdin:

find ... | rename -n 's#/#_#g'

Check the results and if they are fine, remove -n.



来源:https://stackoverflow.com/questions/59678809/find-files-recursively-and-rename-based-on-their-full-path

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!