Exécution d'un script sur une liste de fichiers
J'ai un script qui obtient un fichier .vcf, analyse cela et l'écrit dans un .txt
grep -v "#" file.vcf | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' > vcf_output.txt
J'ai 27 .vcffichiers sur lesquels je veux exécuter ce script en même temps et écrire la sortie de chacun .vcfdans un .txtfichier du nom de celui-ci.vcf
J'ai trouvé ceci dans Google mais rien ne se passe après avoir exécuté cela
for f in *.vcf; do
script "$f" > "${f%.*}.txt"
done
J'ai adopté ça comme ci-dessous
for f in *.vcf; do
grep -v "#" | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' "$f" > "${f%.*}.txt"
done
J'ai aussi essayé ça
(base) loan-mac-13:Pre_Treatment fi1d18$ find -type f -name "*.vcf" | xargs grep -v "#" | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' "$f" > "${f%.*}.txt"
find: illegal option -- t
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
sed: : No such file or directory
(base) loan-mac-13:Pre_Treatment fi1d18$
Comment puis-je faire en sorte que cela fonctionne pour moi?
Réponses
Vous avez converti script "$f"votre sortie google en grep -v "#"(c'est- à -dire qu'il manque le "$f") dans votre script de boucle shell, puis vous l'utilisez à la "$f"place {}et vous l'utilisez au mauvais endroit dans votre xargsscript.
De toute façon, vous n'avez jamais besoin d'un tas de seds et de greps dans une pipleine lorsque vous utilisez awk. Vous n'avez fourni aucun exemple d'entrée / sortie, donc le script awk suivant n'est qu'une traduction directe de votre pipeline existant et il existe probablement une meilleure façon de l'écrire, mais ce script awk est tout ce dont vous avez besoin, pas de boucles shell ou autre :
awk '
FNR == 1 {
close(out)
out = FILENAME
sub(/\.vcf$/,".txt",out)
}
!/#/ {
sub(/chrM/,"MT")
sub(/chrX/,"X")
sub(/chrY/,"Y")
$0 = $1 OFS $2 OFS $2 OFS $4 "/" $5 OFS "+"
gsub(/chr/,"")
print > out
}
' *.vcf
Si vous voulez l'entasser sur moins de lignes comme vous l'avez fait avec votre pipeline grep + seds + awk, vous pouvez simplement utiliser des points-virgules partout où il y a une nouvelle ligne dont vous voulez vous débarrasser sauf après chacune {, par exemple:
awk 'FNR==1{close(out); out=FILENAME; sub(/\.vcf$/,".txt",out)} !/#/{sub(/chrM/,"MT"); sub(/chrX/,"X"); sub(/chrY/,"Y"); $0=$1 OFS $2 OFS $2 OFS $4 "/" $5 OFS "+"; gsub(/chr/,""); print > out}' *.vcf
Vous pouvez utiliser find et xargs pour cela.
Find listera tous les fichiers.
find -type f -name "*.vcf"
Avec xargs nous pouvons opérer sur chaque fichier trouvé.
find -type f -name "*.vcf" | xargs grep -v "#" | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' "$f" > "${f%.*}.txt"
devrait faire le travail?
salutations
Sans altérer aucun de votre flux, ce qui suit devrait fonctionner. Notez que vous n'avez rien entré dans la première commande grep du pipeline. Donc rien ne bougeait.
for f in *.vcf; do
< "$f" grep -v "#" | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' > "${f%.*}.txt"
done