Сценарий оболочки: отправка ввода в фоновый процесс

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

perl -e 'use List::Util 'shuffle'; @k=shuffle(<>); print @k[0..999]' file.bed

Поскольку вы хотите сделать это 10000 раз, я бы рекомендовал интегрировать повторение в сценарий и перетасовать индексы , а не сам массив для ускорения:

$ time perl -e 'use List::Util 'shuffle'; 
            @l=<>; for $i (1..10000){
               open(my $fh, ">","file.$i.bed"); 
               @r=shuffle(0..$#l); 
               print $fh @l[@r[0..999]]
            }' file.bed

real    1m12.444s
user    1m8.536s
sys     0m3.244s

Выше создано 10000 файлов по 1000 строк каждый из файла, который содержал 37000 строк (пример файла повторяется 1000 раз). Как видите, на мою систему ушло чуть больше трех минут.

Объяснение

  • используйте List:: Util 'shuffle'; : импортирует модуль Perl, предоставляющий функцию shuffle () , которая рандомизирует массив.
  • @ l = ; : загрузите входной файл ( ) в массив @ l .
  • для $ i (1.. 10000) {} : запустите этот 10000 раз.
  • @ r = shuffle (0.. $ # l); : $ # l - количество элементов в @ l , поэтому @ r теперь является рандомизированным списком индексных номеров массива @ l (строки входного файла).
  • открыть (мои $ fh, «>», «файл. $ i.bed»); : открыть файл с именем файл. $ i.bed для записи. $ i будет принимать значения от 1 до 10000.
  • print $ fh @ l [@ r [0.. 999]]] : возьмите первые индексы 1000 в перетасованном массиве и напечатайте соответствующие строки (элементы @ l ).

Другой подход заключается в использовании shuf ( thanks @ frostschutz ):

$ time for i in {1..10000}; do shuf -n 1000 file.bed > file.$i.abed; done

real    1m9.743s
user    0m23.732s
sys     0m31.764s

-121--36529-

Есть много способов сделать это, конечно, но почему вы хотите? Это то, что файл fstab является для .

Некоторые идеи:

  • Создайте системное монтирование или автомонтирование (или просто простой сценарий запуска, выполняющий монтирование ).
  • Для запуска монтирования используйте crontab.
  • Наличие сценария запуска в среде рабочего стола.
  • Найдите инструмент в официальных репо или AUR, который сделает это для вас (у меня нет рекомендации).
  • Вставьте злой взлом, где бы вы ни выбрали.

-121--114493-

Изменить в ответ на обновленный вопрос

Поскольку вам нужны только ссылки, каталоги и обычные файлы, и вам не нужно иметь дело с другими типами файлов, которые ls могут идентифицировать (FIFO, сокеты и т.д.), вы можете сделать что-то вроде stat . Для приведенных ниже примеров я создал следующую тестовую среду:

$ ls -l
total 4.0K
-rw-r--r-- 1 terdon terdon    0 Jun 30 23:12 a new?line 
-rw-r--r-- 1 terdon terdon    0 Jun 30 23:12 a space
-rw-r--r-- 1 terdon terdon    0 Jun 30 23:12 a?tab
drwxr-xr-x 2 terdon terdon 4.0K Jun 30 23:11 dir1
lrwxrwxrwx 1 terdon terdon    4 Jun 30 23:13 linktodir1 -> dir1
lrwxrwxrwx 1 terdon terdon    7 Jun 30 23:13 sh -> /bin/sh

Как вы видите, они включают в себя ссылки, ссылки на исполняемые файлы, имя файла с космосом, один с вкладкой (\t ) и один с новой строкой (\n ). Большинство из этих файлов может нарушить ваш подход ls , но stat может справиться с ними правильно:

$ stat --printf "%A\t%N\t%F\n" * 
-rw-r--r--  ‘a new\nline’   regular file
-rw-r--r--  ‘a space’   regular file
-rw-r--r--  ‘a\ttab’    regular file
drwxr-xr-x  ‘dir1’  directory
lrwxrwxrwx  ‘linktodir1’ -> ‘dir1’  symbolic link
lrwxrwxrwx  ‘sh’ -> ‘/bin/sh’   symbolic link

Соответствующие разделы man stat :

-printf = FORMAT

like --format, но интерпретировать обратную косую черту побегов, и не выводить обязательную завершающую новую строку. Если вам нужна новая линия,включать \n в ФОРМАТ

%A права доступа в человекочитаемой форме

%F тип файла

Н, который разыменовывает заключенное в кавычки имя файла с, если символьная ссылка

Примечание, что поля разделяются \t, это означает, что вы сможете иметь дело с пробелом в полях (в именах файлов, например) корректно.

Вы упомянули, что не можете иметь дело с -> . Я не совсем уверен, почему, но вы могли или просто удалить это с sed

$ stat --printf "%A\t%N\t%F\n" * | sed 's/->//' 
lrwxrwxrwx  ‘linktodir1’  ‘dir1’    symbolic link

или заменить им с другой последовательностью:

$ stat --printf "%A\t%N\t%F\n" * | sed 's/->/→/' | grep linktodir
lrwxrwxrwx  ‘linktodir1’ → ‘dir1’   symbolic link

или просто анализируют тип файла.


В зависимости от того, что вы хотите сделать, могло бы быть полезно разделить каждые из этих трех типов файлов, которые вы ищете и соглашение с каждым отдельно. Если так, используйте , находят 1 и опция-printf :

$ find ./ -maxdepth 1 -mindepth 1 -type f -printf '%M\t%P\t%l\n'  ## files
$ find ./ -maxdepth 1 -mindepth 1 -type d -printf '%M\t%P\t%l\n'  ## directories
$ find ./ -maxdepth 1 -mindepth 1 -type l -printf '%M\t%P\t%l\n'  ## links

В этом случае, printf директивы

          %M     File's permissions (in symbolic form, as for  ls).   This
                 directive is supported in findutils 4.2.5 and later.
          %P     File's  name  with  the name of the command line argument
                 under which it was found removed.
          %l     Object of symbolic link (empty string if file  is  not  a
                 symbolic link).

, Вы могли также объединиться, вышеупомянутое в единственную команду (использующий находят оператор-o ), но который позволяет вам использовать -printf для печати произвольной строки в зависимости от типа файла. Например:

$ find ./ -maxdepth 1 -mindepth 1 \( -type l -printf 'link:\t%M\t%P\t%l\n' \) \
-o \( -type d -printf 'dir:\t%M\t%P\n' \) \
-o \( -type f -printf 'file:\t%M\t%P\n' \) 
file:   -rw-r--r--  a?tab
file:   -rw-r--r--  a space
link:   lrwxrwxrwx  linktodir1  dir1
file:   -rw-r--r--  a new?line
dir:    drwxr-xr-x  dir1
link:   lrwxrwxrwx  sh  /bin/sh

команда выше интерпретирует \t и \n правильно, если его вывод не покажут на терминале. Однако для контакта с именами файлов с новыми строками правильно необходимо будет быть осторожными при парсинге (удостоверьтесь, что "строка" начинается [file|dir|link]: ) или использование \0 как разделитель строки в каждом вызов printf вместо \n:

$ find ./ -maxdepth 1 -mindepth 1 \( -type l -printf 'link:\t%M\t%P\t%l\0' \) \
-o \( -type d -printf 'dir:\t%M\t%P\0' \) \
-o \( -type f -printf 'file:\t%M\t%P\0' \)

1 -maxdepth и -mindepth является расширениями GNU, таким образом, этот подход будет только работать на GNU , находят .


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

  1. Shell и readlink

     для f в *; сделать 
     readlink "$f">/dev/null && эхо "$ (readlink-f "$f") (ссылка)" || повторяют "$f";
    готово
    

    Пример произвел:

     / и т.д. (ссылка)
    нечто
    образец. R
    образец. R ~
    

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

  2. , Если это только для вас и не предназначено, чтобы быть проанализированным, просто использовать ls-l :

     $ ls-l
    общие 512116
    - rw-r - r - 1 terdon terdon 100641 30 июня 19:10 er
    lrwxrwxrwx 1 terdon terdon 5 июня 30 19:12 и т.д.->/etc/
    - rw-r - r - 1 terdon terdon 524288000 30 июня 19:10 нечто
    - rwxr - r - 1 terdon terdon 353 30 июня 15:22 образца. R
    - rwxr - r - 1 terdon terdon 249 30 июня 14:51 образца. R ~
    

    Это ясно укажет на ссылки с ссылка-> цель .

0
17.07.2015, 22:07
2 ответа

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

В основном я создал именованный канал (названный ".in") и отправил ему информацию. Я создал функцию, так что все, что мне нужно сделать, это тип "i [input]"

SCRIPT=".dim_import/xdir"

while true;
do
    size=$(du -s .dim_import | cut -b 1-2)
    if [ $size -gt 32 ]; then
        if [ ! -f ~/files ]; then
          echo "SR Number (i [number]): "; 
          read srNum < ~/.in
          $SCRIPT $srNum
          sleep 10
          ~/scripts/listSR
        fi
    fi
    if [ ~/ ]
    sleep 5
done

Функция профиля:

function i
{
  set +u
  echo $1 > ~/.in
  set -u
}
0
28.01.2020, 02:27

Вы говорите о запуске tmux из вашего файла конфигурации bash?

В этом случае вы должны запустить tmux, предваряя его ключевым словом exec :

exec tmux ...

, чтобы bash был полностью заменен на tmux.

-121--166581-

Это просто фея с sed :

sed -e '/^cat$/d' <file

/^ cat $/ только линия соответствия, которая содержит только cat , затем d удалить эту линию.

или awk :

awk '!/^cat$/' <file

или grep :

grep -v '^cat$' <file
-121--174572-

Ну, реальный вопрос в том, какие входные данные вы действительно хотите отправить в СЦЕНАРИЙ. Если вы хотите, чтобы он имел пустой ввод, то выполните:

$SCRIPT < /dev/null

Если вы хотите дать ему какой-то конкретный ввод, как содержимое $ size, то выполните:

echo "$size" | $SCRIPT

Если вы хотите ввести ввод, то вам придется положить его обратно в Forground, чтобы ввести ваш ввод, а затем поместить его на фон снова. Возможность сделать это зависит от того, имеет ли ваша оболочка управление заданиями (большинство делают, но оригинальная оболочка Борна не). Выполните следующие действия:

  • Запустите fg% watcher или fg% 1 (используя любой номер задания, который вы видите после выполнения заданий -l ), чтобы вывести процесс на передний план.
  • Введите необходимые входные данные с последующим возвращением.
  • Введите control-Z, чтобы вернуть его в фоновый режим (или используйте stty -a и проверьте наличие susp , чтобы узнать, что такое стоп-символ).
  • После того, как программа будет остановлена элементом управления-Z, поместите ее обратно в фоновый режим с bg% 1 (или каким бы ни было число).

Еще одним ответом было бы иметь именованную трубу. Вот пример (используя tr вместо вашего сценария только для показа):

$ mkfifo my_fifo
$ tr a-z A-Z < my_fifo &
$ exec 6> my_fifo
$ echo here is some input for the fifo >&6
$ HERE IS SOME INPUT FOR THE FIFO

Сначала вы запускаете сценарий, беря его из fifo (важно сначала запустить сценарий). Затем exec 6 >... делает файловый дескриптор 6 оболочки записанным в fifo. Затем при необходимости отправки выходных данных записывайте их в дескриптор файла 6 (через > & 6 ). Обратите внимание, что последнее "HERE IS"... было напечатано не мной, это просто выход tr.

3
28.01.2020, 02:27

Теги

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