Скрипт Bash для удаления и переименования файлов в зависимости от размера и именования

0

У меня есть каталоги с несколькими конфликтующими файлами, и я ищу способ сортировки, присвоения имен и удаления дубликатов, основанных на отдельном шаблоне, основанном на имени и размере файла. Хотя мои знания сценариев bash очень ограничены, поэтому я ищу какое-либо руководство по созданию этого.

  • Дубликаты могут различаться по именам файлов и размеру файла
  • Если есть дубликат, имя файла заканчивается на _conflict-yyyymmdd-hhmmss.ext
  • Всегда есть нефиксированная версия файла, но она может быть повреждена
  • Файл с наибольшим размером всегда правильный
  • Несколько файлов могут иметь одинаковый размер, в этом случае удаление дубликатов и переименование файла является наиболее желательным
  • Конечный файл всегда должен быть без префикса

Вот пример возможных сценариев:

   FILE                                                   SIZE        DESIRED ACTION
a. /path/to/dir1/FileName1.ext                            0           rm
b. /path/to/dir1/FileName1_conflict-20130324-231953.ext   21624832    mv b a
c. /path/to/dir1/FileName1_conflict-20130326-080529.ext   21624832    rm

a. /path/to/dir2/FileName2.ext                            25432935    -
b. /path/to/dir2/FileName2_conflict-20130324-092544.ext   0           rm
c. /path/to/dir2/FileName2_conflict-20130326-212307.ext   25432935    rm

a. /path/to/dir3/FileName3.ext                            0           rm
b. /path/to/dir3/FileName3_conflict-20130324-214501.ext   23422234    mv b a

a. /path/to/dir4/FileName4.ext                            0           rm
b. /path/to/dir4/FileName4_conflict-20130324-110541.ext   14423       rm
c. /path/to/dir4/FileName4_conflict-20130326-030512.ext   25432935    mv c a

Любая помощь и предложения с этим будет принята с благодарностью.


Обновление: решение

Очень жаль, что я не привел четких примеров того, что я пробовал, мои первые попытки были беспорядочными. Я не искал законченный сценарий, просто помогу советом. Во всяком случае, я провел день, изучая сценарии оболочки (это в значительной степени моя первая попытка), и я нашел решение, которое работает для меня. Вы можете найти мой скрипт ниже:

#!/bin/bash

# find all files without _conflict-suffix
find ./ -type f ! -name "*_conflict*" -print0 | while read -d $'\0' file
do
  # regex to get dir and partial name
  if [[ $file =~ ^(.*\/)(.*)(\..*)$ ]] ; then
    dir="${BASH_REMATCH[1]}"
    # file size in bytes
    size=`wc -c < "$file"`

    # look for matching files with _conflict-suffix
    find "${dir}" -name "${BASH_REMATCH[2]}_conflict-*${BASH_REMATCH[3]}" -print0 | while read -d $'\0' conflict
    do
      # conflicting filesize in bytes
      conSize=`wc -c < "$conflict"`
      # check if conflict-file is bigger
      if [[ $size -lt $conSize ]] ; then
        # It is! Remove, rename, and update variable with new size
        rm "${file}"
        mv "${conflict}" "${file}"
        set size=conSize
      else
        # It isn't, remove the trash.
        rm "${conflict}"
      fi
    done
  fi
done

Посмотрите на ответ @ NSD для другого решения.

Саймон Кьельберг
источник
2
что вы пытались .... сталкивались ли вы с какими-либо проблемами / ошибками при их реализации или вы хотите, чтобы кто-то написал полный сценарий? (начать с размера можно найти, используя имя файла du -sh и условие if для проверки и переименования ... это то, что требует ваш вопрос, верно !!)
n13
ваш пример помогает ... можете ли вы сократить список правил следующим образом: найдите набор самых больших файлов (по размеру) в каталоге, если в наборе есть префикс , удалите все остальные, переместите первый большой файл с префиксом в без префикса и удалите все остальные ... ???
user1055604
@SimonKberg +1 за приложенное усилие
n13

Ответы:

0

хм .... как-то плохо, что вы проголосовали, у меня есть кое-что, с чего можно начать.

Я прочитал правила, и, кажется, у вас уже есть готовое описание того, что должно быть сделано для какого файла ..... следующий пример сценария использует этот дескриптор, чтобы определить, какое действие необходимо предпринять, а затем выполнить это (Примечание - mv и команды rm прокомментированы, я использовал echo для тестирования, раскомментируйте их, чтобы получить фактическое действие)

код ::

Кайдзен ~ / so_test / test $ cat ztest.sh

## remove header
 sed -i '1d' zlst ;
 :>ztmp ;


## loop to parse the file entries one by one
 while read line
 do

 echo $line ;
 file=`echo $line | tr -s " " | cut -d" " -f2`;
 file=`basename $file .ext` ;   #3 used to filter a selection for action
 echo $file ;

 dir=`echo $line | tr -s " " | cut -d" " -f2`;
 dir=`basename $dir` ;   #3 used to change the directory to where action is to be performed
 cd $dir  &&  echo $dir ;


grep -i $file zlst > ztmp ;
axn=`echo $line | tr -s " " | cut -d" " -f4` ;

 ## case to select the course of axn
 case $axn in

  mv )
      echo `echo $line | tr -s " " | cut -d" " -f4-`;
      file=`echo $line | tr -s " " | cut -d" " -f5` ;
      old_name=`grep -w "${file}" ztmp | cut -d" " -f2` ;
      old_name=`basename $old_name` ;
      file=`echo $line | tr -s " " | cut -d" " -f6` ;
      new_name=`grep -w "${file}" ztmp | cut -d" " -f2` ;
      new_name=`basename $new_name` ;
      echo " mv $old_name $new_name ;" ;
      #mv $old_name $new_name ;
      ## break ;;
      ;;

      rm )
      #file=`echo $line | tr -s " " | cut -d" " -f4-`;
      echo "rm $file" ;
      #rm $file ;
      ## break ;;
      ;;

      * )
       :
       echo "do nothing " ;
       #break ;;
       ;;
  esac

 ##empty the tmp file
 :> ztmp ;

 done < zlst  ## end the while loop @ EOF.

вывод ::

Kaizen ~/so_test/test $ . ./ztest.sh

a. /path/to/dir1/FileName1.ext 0 rm
FileName1
rm FileName1

b. /path/to/dir1/FileName1_conflict-20130324-231953.ext 21624832 mv b a
FileName1_conflict-20130324-231953
 mv b a
 mv FileName1_conflict-20130324-231953.ext FileName1_conflict-20130324-231953.ext ;

c. /path/to/dir1/FileName1_conflict-20130326-080529.ext 21624832 rm
FileName1_conflict-20130326-080529
rm FileName1_conflict-20130326-080529

.ext
do nothing

a. /path/to/dir2/FileName2.ext 25432935 -
FileName2
do nothing

b. /path/to/dir2/FileName2_conflict-20130324-092544.ext 0 rm
FileName2_conflict-20130324-092544
rm FileName2_conflict-20130324-092544

 c. /path/to/dir2/FileName2_conflict-20130326-212307.ext 25432935 rm
 FileName2_conflict-20130326-212307
 rm FileName2_conflict-20130326-212307

.ext
do nothing

a. /path/to/dir3/FileName3.ext 0 rm
FileName3
rm FileName3

b. /path/to/dir3/FileName3_conflict-20130324-214501.ext 23422234 mv b a
FileName3_conflict-20130324-214501
mv b a
mv FileName3_conflict-20130324-214501.ext FileName3_conflict-20130324-214501.ext ;

.ext
do nothing

a. /path/to/dir4/FileName4.ext 0 rm
FileName4
rm FileName4

b. /path/to/dir4/FileName4_conflict-20130324-110541.ext 14423 rm
FileName4_conflict-20130324-110541
rm FileName4_conflict-20130324-110541

c. /path/to/dir4/FileName4_conflict-20130326-030512.ext 25432935 mv c a
FileName4_conflict-20130326-030512
mv c a
mv FileName4_conflict-20130326-030512.ext FileName4_conflict-20130326-030512.ext ;

Пожалуйста, обратите внимание : для проверки размера я не включил это в код, простое условие if в цикле while подойдет .... хотя вам нужно будет добавить это.

надеюсь это поможет !!

n13
источник
Спасибо, это было действительно полезно. Я закончил тем, что написал свое собственное решение, и я обновлю вопрос с ним. Отмечу ваш ответ, хотя, поскольку вопрос был настолько неопределенным (я не ожидал, что кто-то напишет целый сценарий, просто предложите некоторую помощь, поскольку я никогда раньше не писал никакого сценария оболочки). Еще раз спасибо
Саймон Кьельберг