How to move files in Linux based on its name in a

2019-08-20 11:59发布

I would need to move a series of files in certain folders via scripts. The files are of the format xxxx.date.0000 and I have to move them to a folder whose name is the same value given.

For example:

  • file hello.20190131.0000
  • in folder 20190131

The ideal would be to be able to create folders even before moving files but it is not a priority because I can create them by hand. I managed to get the value of dates on video with

 ls * .0000 | awk -F. '{Print $ 2}'

Does anyone have any suggestions on how to proceed?

标签: linux bash shell
3条回答
闹够了就滚
2楼-- · 2019-08-20 12:10

You can do that with rename, a.k.a. Perl rename.

Try it on a COPY of your files in a temporary directory.

If you use -p parameter, it will make any necessary directories for you automatically. If you use --dry-run parameter, you can see what it would do without actually doing anything.

rename --dry-run -p 'my @X=split /\./;  $_=$X[1] . "/" . $_'   hello*

Sample Output

'hello.20190131.0000' would be renamed to '20190131/hello.20190131.0000'
'hello.20190137.0000' would be renamed to '20190137/hello.20190137.0000'

All you need to know is that it passes you the current name of the file in a variable called $_ and it expects you to change that to return the new filename you would like.

So, I split the current name into elements of an array X[] with the dot (period) as the separator:

my @X = split /\./

That gives me the output directory in $X[1]. Now I can set the new filename I want by putting the new directory, a slash and the old filename into $_:

$_=$X[1] . "/" . $_

You could also try this, shorter version:

rename --dry-run -p 's/.*\.(\d+)\..*/$1\/$_/' hello*

  • On ArchLinux, the package you would use is called perl-rename.
  • On debian, it is called rename
  • On macOS, use homebrew like this: brew install rename
查看更多
可以哭但决不认输i
3楼-- · 2019-08-20 12:16

The initial awk command provided much of the answer. You just need to do something with the directory name you extract:

A simple option:

ls *.0000 | awk -F. '{printf "mkdir -p '%s'; mv '%s' '%s';",$2,$0,$2}' | sh

This might be more efficient with a large number of files:

ls *.0000 | awk -F. '{print $2}' |\
sort | uniq |\
while read dir; do
    mkdir -p "$dir"
    mv *."$dir".0000 "$dir"
done
查看更多
等我变得足够好
4楼-- · 2019-08-20 12:23

I would do something like this:

ls *.0000 |\
  sort |\
    while read f; do
      foldername="`echo $f | cut -d. -f2`"
      echo mkdir +p "$foldername/"
      echo mv "$f" "$foldername/"
    done

i.e.: For eache of your files, I build the folder name using the cut command with a dot as field separator, and getting the second field (the date in this case); then I create that folder with mkdir -p (the -p flag avoids any warning if the folder should exist already), and finally I move the file to the brand new folder.

查看更多
登录 后发表回答