Невозможно атомарно заменить каталог другим каталогом. Вы можете переместить старый каталог, а затем создать новый:
mv statistics backup-xx
mkdir statistics
Но это оставляет небольшой промежуток времени, в течение которого статистики
не существует. Это проблема, если какой-то процесс может удалить файлы в каталоге в любое время.
Для эффективной атомарной замены каталога вам необходимо использовать символические ссылки. Создайте каталог, имя которого включает период времени с самого начала:
mkdir "statistics-$(date +%Y%m%d)"
(или любое другое соглашение об именовании каталогов, которое вы хотите выбрать). Создайте символическую ссылку с фиксированным именем на текущее местоположение:
ln -s … statistics
Чтобы заменить каталог, сначала создайте новый каталог и новую символическую ссылку, а затем переместите ее, чтобы перезаписать старую символическую ссылку. Обратите внимание, что ни простой mv
в символической ссылке, ни простой ln -s
этого не сделают: они создадут запись внутри целевого каталога. GNU coreutils ln -snf
также не подходит, потому что он удаляет существующую символическую ссылку перед созданием новой, что оставляет небольшое временное окно, в течение которого путь не существует. Вы можете использовать GNU coreutils mv -T
для новой символической ссылки.
new_dir="statistics-$(date +%Y%m%d)"
mkdir "$new_dir"
ln -s statistics.new
mv -Tf statistics.new statistics
На случай, если кто-то интересуется будущим: Вот мой быстрый и грязный способ сделать это с помощью perl:
#!usr/bin/perl
use warnings;
use strict;
open(FILE, "ABC123.fa");
my $line_=<FILE>;
$line_=readline(*FILE) if $line_=~/>/;
close(FILE);
if($line_ =~ /L|M|F|W|K|Q|E|S|P|V|I|Y|H|R|D/){
print "Protein\n"
}
else {
print "Nucleotide\n"
}
Я выполняю его, используя:
perl format_tester.pl
перед каждым запуском этого кода я просто заменяю «ABC123.fa» на «DEF123.fa», используя подход sed:
sed -i 's/ABC123.fa/DEF123.fa/g' format_tester.pl
Использованиеawk
:
for name in folder/*; do
# skip this name if it's not the name of a file
[ ! -f "$name" ] && continue
awk 'NR == 1 && !/^>/ {
printf("Not a fasta file: %s\n", FILENAME)
skip=1; exit
}
!/^>/ && /[LMFWKQESPVIYHRD]/ {
printf("Protein fasta file: %s\n", FILENAME)
skip=1; exit
}
END {
if (!skip) printf("Probably a DNA fasta file: %s\n", FILENAME)
}' "$name"
done
Это просматривает все имена в каталоге с именем folder
. Он пропускает имена подкаталогов (не -файлов )и применяет сценарий awk
к найденным файлам.
Тогда
Проверяет, что файл является файлом fasta, проверяя >
в начале первой строки. Если в начале первой строки нет >
, он сообщает об ошибке в файле и завершает работу.
Для каждой строки, не начинающейся с >
, проверяется, есть ли в строке символ белка. Если есть, он сообщает о файле как о файле белкового быстрого доступа и завершает работу.
В конце концов, если мы туда доберемся, это возможно, файл фаста ДНК, и код сообщает об этом. Обратите внимание, что даже если это маловероятно, это все же может быть белковый файл fasta, поскольку символы ДНК-аминокислот также являются частью набора символов белка.
Переменная skip
устанавливается в 1, когда мы выходим из-за того, что определили, что файл не является fasta-файлом или является белковым fasta-файлом. Проверяя эту переменную в блоке END
, мы узнаем, прибыли ли мы туда из-за раннего exit
или из-за нехватки данных (, и в этом случае, вероятно, это файл fasta ДНК ).