我正在尝试从python代码执行bash脚本。 bash脚本在for循环内的管道中包含一些grep命令。当我运行bash脚本本身时,它没有给出任何错误,但是当我在python代码中使用它时,它说:grep:write error。
我在python中调用的命令是:
subprocess.call("./change_names.sh",shell=True)
bash脚本是:
#!/usr/bin/env bash
for file in *.bam;do new_file=`samtools view -h $file | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done
我想念什么?
答案 0 :(得分:1)
在运行不需要命令行中任何内容的外壳程序的简单命令时,请勿使用shell=True
。
subprocess_call(["./change_names.sh"])
shell脚本中存在多个问题。这是评论式重构。
#!/usr/bin/env bash
for file in *.bam; do
# Use modern command substitution syntax; fix quoting
new_file=$(samtools view -h "$file" |
grep -P '\tSM:' |
# refactor to a single sed script
sed -n 's/.\+SM:\([^\t]\+\).*/\1/p;q')
# Fix quoting some more; don't use rename
mv "$file" "$new_file.bam"
done
grep -P
在这里似乎不是必需的或有用的,但是由于没有输入看起来像的例子,我也很犹豫地将其重构为sed
脚本。我希望我已经正确地猜出了您的sed
版本使用的\+
和\t
转义符不是完全可移植的。
更好的解决方案可能是将更多内容重构到Python脚本中。
import glob
for file in glob.glob('*.bam'):
new_name = subprocess.check_output(['samtools', 'view', '-h', file])
for line in new_name.split('\n'):
if '\tSM:' in line:
dest = line.split('\t')[0].split('SM:')[-1] + '.bam'
os.rename(file, dest)
break
答案 1 :(得分:0)
您好,请尝试以下修改,以解决您的问题。
for file in *.bam;do new_file=`unbuffer samtools view -h $file | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done
否则尝试将您的标准错误重定向到dev / null,如下所示:
for file in *.bam;do new_file=`samtools view -h $file >2>/dev/null | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done
此命令samtools view -h $file
的实际问题在于从python
运行脚本时,应提供如下完整路径:-
/fullpath/samtools view -h $file