Bash -Как реорганизовать файлы на основе дат в их именах?

Основное недоразумение здесь, по-видимому, заключается в том, что изменение символической ссылки во время ее записи изменит что-либо ожидаемым образом.

Нет. Как только будет открыт фактический файл (, устройство или канал ), все действия будут относиться к открытому файлу, игнорируя все, что происходит, например, с символической ссылкой, указывающей на него. На самом деле, это не ограничивается символическими ссылками, но в равной степени относится и к «жестким» ссылкам, которые вообще заставляют файлы иметь имена :. В unixoid-системах вы можете перемещать или даже удалять (! )файл (НЕ :Перезаписывать! )что какой-то процесс был открыт, и процесс не увидит никаких изменений, пока не закроет файл.

3
19.01.2021, 02:08
3 ответа

Вот мое предложение, если я правильно понял:

for i in *.nc; do 
  [[ "$i" =~ _([0-9]{8})[_.] ]] && d="${BASH_REMATCH[1]}"
  mkdir -p "${d:0:4}/${d:4:2}"
  mv "$i" "${d:0:4}/${d:4:2}"
done
6
18.03.2021, 22:36

Предполагая, что дата всегда находится в одном и том же месте в имени файла, поместите это в скрипт:

#!/bin/bash
#
while $# -gt 0 ; do
    file="$1"
    shift
    year="$( echo "$file" | cut -c 14-17)"
    mnth="$( echo "$file" | cut -c 18-19)"
    [[ -d $year/$mnth ]] || mkdir -p $year/$mnth
    echo mv "$file" $year/$mnth
done

И вызовите скрипт с помощью:

find. -maxdepth 1 -type f -name '*201*' -printf | \
    xargs -r the_script

Прочитать man bash find xargs mkdir mv.

Удалите echo, если хотите сделать это по-настоящему.

4
18.03.2021, 22:36

Цикл по годам и месяцам:

#!/bin/bash

for year in {2001..2020} ; do
  mkdir $year
  for month in {01..12} ; do
    mkdir $year/$month
    mv gpm_cressman_${year}${month}* $year/$month
  done
done

Если у вас слишком много файлов с длинными именами в год и месяц (, вы утверждаете, что «тысячи» ), bashмогут достичь своего предела («слишком длинный список аргументов» ). Либо временно увеличьте ulimit , либо используйтеxargs:

#!/bin/bash

for year in {2001..2020} ; do
  mkdir $year
  for month in {01..12} ; do
    mkdir $year/$month
    find -maxdepth 1 -type f -name "gpm_cressman_${year}${month}*" |
      xargs -I '{}' mv '{}' $year/$month
  done
done
5
18.03.2021, 22:36

Теги

Похожие вопросы