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?
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
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.
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