Можно ли перемещать файлы в группах в каталог, который нужно менять каждые четыре файла? - PullRequest
0 голосов
/ 25 февраля 2019

Я понимаю, что название, возможно, не было ясным, но я не мог найти лучший способ выразить это.По сути, я хотел бы знать, можно ли указать оболочке

a) переместить первые четыре файла в каталог a

b) переместить вторую группу из четырех файлов в каталог bи т. д. для примерно тысячи файлов.

Однако имена каталогов a и директории b (и всех остальных) не имеют ничего общего, поэтому я понимаю, что мне придется создать скрипт, который следит

a) количество перемещенных файлов,

b) количество каталогов, в которых уже есть все необходимые файлы, и

c) в какой каталог записать следующий(Я предполагаю, что это будет связано с каким-то назначенным оболочкой числовым упорядочением каталогов).

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

Спасибо за ваше времяme.

РЕДАКТИРОВАТЬ: Файлы, которые должны быть перемещены, являются .zip файлами, в форме 'x_y_z.zip', где

x = строка, общая для всех файлов

y = строка, которая определяет, какой файл принадлежит какой группе

z = строка, уникальная для каждого n-го файла в каждой группе.

Некоторые группы содержат меньше файлов,но никогда не бывает группы, в которой более четырех файлов.

Что мне нужно сделать, так это просмотреть каталог, файл за файлом и переместить файлы .zip, которые совместно используют «y», в другой каталог.который содержит эту группу и только эту группу.Проблема, с которой я сталкиваюсь, состоит в том, что имена каталогов не могут содержать «y», и поэтому мне нужен способ получить уведомление оболочки, когда «y» изменилось, и переместить файл в следующий каталог в списке.

РЕДАКТИРОВАТЬ 2: Итак, я в общих чертах разработал то, что мне нужно сделать - если я могу поместить все имена zip-файлов в файл .txt и все имена целевых каталогов в другой, я могу сказатьоболочка для чтения из directory.txt и использования его в качестве цели команды mv.Единственная проблема, с которой я сталкиваюсь, - как заставить оболочку переходить в следующий каталог, когда меняется «y», но я думаю, что справился с этим.Все, что мне сейчас нужно, это команда mv первого файла в file.txt в первый каталог в directory.txt.Вот что у меня есть:

!/bin/bash

cd ~/Downloads/ZIP
ls -rt *.zip > file.txt

a=1

for i in *.zip
do
    mv 'line a of file.txt' 'line a of directory.txt' 
    let a=a+1
done

Команда ls -rt необходима, потому что, хотя файлы имеют какую-то систему идентификации, она не имеет абсолютно никакого отношения к используемой мной системе id,но, к счастью, я создал файлы в том порядке, в котором каталоги перечислены в файле directory.txt.

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

Дублированные файловые дескрипторы для спасения.
Как это?

last=''                          # pre-sets the comparator to empty
while read -u 4 file             # read a filename 
do IFS=_ read x y z <<< "$file"  # splits filename on _ for y
   if [[ "$y" != "$last" ]]      # when it has changed
   then read -u 3 dir            # reads from the dirs file
        last="$y"                # updates comparator
   fi
   mv "$file" "$dir/"            # does the move
done 3< dirs 4< files            # this assigns the streams to fd's

Стандартный fd (файловый дескриптор) для stdin в 0. Мы назначаем новый fd из 3 специально какфайл dirs, а другой как 4 для файла имен файлов.Это сделано для области цикла со строкой

done 3< dirs 4< files

. Вы можете изменить имена файлов.Для тестирования я использовал dirs и files.

read -u 3 dir явно читает из fd # 3, поэтому он не потребляет ничего другого, например имени файла.
read -u 4 fileчитает явным образом из fd # 4, поэтому он не потребляет ничего другого, например, каталога.
Это позволяет одновременно читать их оба.

Моя страница справочника, для вашего удобства:

read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t  timeout]  [-u  fd]  [name
   ...]
  One line is read from the standard input, or from the
  file descriptor fd supplied as an argument to the -u 
  option, and the first word is assigned to the first name,
  the second word to the second name, and so on, with 
  leftover words and their intervening separators assigned
  to the last name.  If there are fewer words read from the 
  input stream than names, the remaining names are assigned
  empty values. The characters in IFS are used to split
  the line into words. The backslash character (\) may be
  used to remove any special meaning for the next character
  read and for line continuation.

Options, if supplied, have the following meanings:
  -u fd      Read input from file descriptor fd.

и для полноты ...

  -a aname   The  words are assigned to sequential indices
             of the array variable aname, starting at 0. 
             aname is unset before any new values are
             assigned.  Other name arguments are ignored.
  -d delim   The first character of delim is used to 
             terminate the input line, rather than newline.
  -e         If the standard input is coming from a
             terminal, readline (see READLINE above) is used
             to obtain the  line. Readline uses the current
             (or default, if line editing was not previously
             active) editing settings.
  -i text    If readline is being used to read the line,
             text is placed into the editing buffer before
             editing begins.
  -n nchars  read returns  after reading nchars characters
             rather than waiting for a complete line of 
             input, but honor a delimiter if fewer than 
             nchars characters are read before the
             delimiter.
  -N nchars  read returns after reading exactly nchars
             characters rather than waiting for a complete
             line of input, unless EOF is encountered or
             read times out. Delimiter characters
             encountered in the input are not treated
             specially and do not cause read to return until
             nchars characters are read.
  -p prompt  Display prompt on standard error, without a
             trailing newline, before attempting to read any
             input. The prompt is displayed only if input is
             coming from a terminal.
  -r         Backslash does not act as an escape character. 
             The backslash is considered to be  part  of the                     
             line. In particular, a backslash-newline pair 
             may not be used as a line continuation.
  -s         Silent mode.  If input is coming from a
             terminal, characters are not echoed.
  -t timeout Cause read to time out and return failure if a
             complete line of input is not read within
             timeout seconds. timeout may be a decimal
             number with a fractional portion following the
             decimal point. This  option  is only effective
             if read is reading input from a terminal, pipe,
             or other special file; it has no effect when
             reading from regular files. If timeout is 0,
             read  returns  success if input is available on
             the specified file descriptor, failure
             otherwise. The exit status is greater than 128
             if the timeout is exceeded.
0 голосов
/ 26 февраля 2019

Я думаю, просто основываясь на моем наивном прочтении вашей проблемы, вы, возможно, немного переосмыслили ее.Если y - это строка, которая идентифицирует группу, тогда вам просто нужно переместить каждый файл в папку «y», основываясь на том, что «y» находится в каждом файле?

что-то вроде:

#!/bin/bash

for filename in ./x*; do
    middle=$( echo "$filename" | cut -d\_ -f2 |tr -d "\n" | od -An -t uC)
    mkdir -p $middle;
    mv $filename $middle;
done

Это переместит каждый файл в папку «y» на основе «y» для этого файла.Если каталог не существует, он создаст его.Он должен быть запущен из того же каталога, что и файлы.

Если я неправильно понял, и вам действительно нужно проверить сумму, входящую в каждый каталог, должно быть достаточно просто добавить это в качестве другого цикла внутри существующего,просто читая значение 'z'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...