저는 xonsh와 Python을 배우기 시작했습니다. 저는 주로 Python으로 쉘 스크립트를 작성하고 싶고 기존의 중소 규모 bash 스크립트를 많이 대체하고 싶습니다.
나는 아래에 제공된 bash 스크립트로 시작했습니다(몇 가지 설명이 추가됨). 수동으로 Python으로 변환했습니다(아래 참조).내 Python을 개선하거나 더 간결하게 만들 수 있는 부분을 지적해 주세요.
#!/bin/bash
while IFS= read -r line;
do
echo $line | grep '^Path=' >/dev/null 2>&1
if [[ $? -eq 0 ]]; then \
path=~/.mozilla/firefox/$(echo $line | sed 's/^Path=//')/user.js; #open the user.js file for each profile
if [[ -f ${path} ]]; then \
echo "Processing: path: ${path}";
grep 'browser.ctrlTab.sortByRecentlyUsed' ${path} >/dev/null 2>&1 #check if this property already exists
if [ $? -ne 0 ]; then \
echo 'user_pref("browser.ctrlTab.sortByRecentlyUsed", true);' >> ${path}; #did not exist, so append it to end of file
else
sed -i 's/browser.ctrlTab.sortByRecentlyUsed",.*false/browser.ctrlTab.sortByRecentlyUsed", true/' ${path} #did exist, so change it to desired value if needed
fi
echo "updated ctrlTab.sortByRecentlyUsed for $path"
grep 'browser.tabs.loadBookmarksInTabs' ${path} >/dev/null 2>&1
if [ $? -ne 0 ]; then \
echo 'user_pref("browser.tabs.loadBookmarksInTabs", false);' >> ${path};
else
sed -i 's/browser.tabs.loadBookmarksInTabs",.*true/browser.tabs.loadBookmarksInTabs", false/' ${path}
fi
echo "updated loadBookmarksInTabs for $path"
fi
fi
done < ~/.mozilla/firefox/profiles.ini #read this file to find the path to all profiles
이제 작동하는 Python 솔루션이 생겼지만 예상했던 것보다 훨씬 더 복잡해 보입니다. 내 목표는 이 상황에 대한 짧고 빠른 해결책을 작성하는 것입니다. 나는 지금으로서는 대규모 Python 프로그램을 작성할 생각은 없습니다. 일단 충분히 배우면 xonsh를 광범위하게 사용할 수 있기를 바랍니다. 분명히 학습을 위해 포함했던 인쇄문을 제거할 수 있을 것 같습니다. 그 외에도 아래에 표시된 솔루션을 어떻게 개선하거나 단축할 수 있습니까?
특히, 나는 다음을 사용할 계획이었습니다.피스사이드그리고 파이썬파일 입력하지만 이것들로는 실행 가능한 솔루션을 구현할 수 없습니다.
import sys
from pathlib import Path
import re
trgt_file='user.js'
myuser='mountainx'
base_path = Path('/home/' myuser '/.mozilla/firefox')
if not base_path.is_dir():
print("ERROR:", base_path, "does not exist.")
# exit()
else:
print("OK: processing", base_path)
ini_path = Path(base_path / 'profiles.ini')
if not ini_path.is_file():
print("ERROR:", ini_path, "cannot be opened.")
# exit()
else:
print("OK: opening", ini_path)
match_ctrltab = False
match_bookmark_found = False
pro_path_re = re.compile(r'^Path=(\w+)$')
ctrltab_sort_regex = re.compile(r'^/*?user_pref\("browser\.ctrlTab\.sortByRecentlyUsed.*$', re.M)
ctrltab_sort_repls = 'user_pref("browser.ctrlTab.sortByRecentlyUsed", true);'
bookmark_open_regex = re.compile(r'^/*?user_pref\("browser\.tabs\.loadBookmarksInTabs.*$', re.M)
bookmark_open_repls = 'user_pref("browser.tabs.loadBookmarksInTabs", false);'
with open(ini_path, "r") as profiles_ini:
for any_line in profiles_ini:
m_path = pro_path_re.match(any_line)
if not m_path is None:
p_path = m_path.group(1)
print("p_path:", p_path)
profile_path = Path(base_path / p_path)
print("profile_path:", profile_path)
if profile_path.is_dir():
print("The profile path is", profile_path)
user_js_path = Path(profile_path / trgt_file)
if Path(user_js_path).is_file():
print("OK: valid file:", user_js_path)
with open(user_js_path, 'r+') as file_userjs:
#read the file contents
file_contents = file_userjs.read()
match_ctrltab = ctrltab_sort_regex.search(file_contents)
if match_ctrltab is None:
file_contents = file_contents + '\n' + ctrltab_sort_repls
print('No match: added line to end of file contents:', ctrltab_sort_repls)
else:
file_contents = ctrltab_sort_regex.sub(ctrltab_sort_repls, file_contents)
print('Match found. Replaced line in file for ctrltab_sort')
match_bookmark = bookmark_open_regex.search(file_contents)
if match_bookmark is None:
file_contents = file_contents + '\n' + bookmark_open_repls
print('No match: added line to end of file contents:', bookmark_open_repls)
else:
file_contents = bookmark_open_regex.sub(bookmark_open_repls, file_contents)
print('Match found. Replaced line for bookmark_open_regex')
file_userjs.seek(0)
file_userjs.truncate()
file_userjs.write(file_contents)
else:
print("SKIPPED: invalid file:", user_js_path)
제가 테스트하고 있는 날짜는 다음과 같습니다. 일반적인 솔루션은 모든 Firefox user.js 또는 prefs.js 파일에서 작동합니다.
file_contents = """
user_pref("media.gmp-gmpopenh264.abi", "x86_64-gcc3");
user_pref("media.gmp-gmpopenh264.autoupdate", false);
user_pref("media.gmp-gmpopenh264.enabled", false);
user_pref("media.gmp-gmpopenh264.lastUpdate", 1571947201);
user_pref("media.gmp-gmpopenh264.version", "1.8.1");
user_pref("browser.ctrlTab.sortByRecentlyUsed",false);
//user_pref("browser.ctrlTab.sortByRecentlyUsed", true);"""
답변1
이것은 내가 직접 생각해낸 것 중 단연 최고입니다.
저는 두 개의 함수를 작성하여 modtest라는 디렉터리에 저장했습니다(그리고 파일을 ffutils.py로 저장했습니다).
touch modtest/__init__.py
바라보다https://stackoverflow.com/a/33770042이에 대해 자세히 알아보세요.
import sys
from pathlib import Path
import re
def find_profile_dirs(user=None, debug=False):
profiles = []
if user is None:
base_path = Path('~/.mozilla/firefox').expanduser()
else:
base_path = Path('/home') / user / '.mozilla/firefox'
if not base_path.is_dir():
print("ERROR:", base_path, "does not exist.")
elif debug:
print("OK: processing", base_path)
ini_path = Path(base_path / 'profiles.ini')
if not ini_path.is_file():
print("ERROR:", ini_path, "cannot be opened.")
elif debug:
print("OK: opening", ini_path)
pro_path_re = re.compile(r'^Path=(\w+)$')
with open(ini_path, "r") as profiles_ini:
for any_line in profiles_ini:
m_path = pro_path_re.match(any_line)
if not m_path is None:
p_path = m_path.group(1)
if debug:
print("p_path:", p_path)
profile_path = Path(base_path / p_path)
if debug:
print("profile_path:", profile_path)
if profile_path.is_dir():
profiles.append(profile_path)
print("The profile path is", profile_path)
return profiles
# profiles_paths is a list of Paths of all Firefox profiles to process
def process_userjs(searchExp, replaceExp, profiles_paths, debug=False):
match_result = None
search_regex = re.compile(searchExp, re.M)
trgt_file='user.js'
for profile_path in profiles_paths:
user_js_path = Path(profile_path / trgt_file)
if Path(user_js_path).is_file():
if debug:
print("OK: valid file:", user_js_path)
with open(user_js_path, 'r+') as file_userjs:
file_contents = file_userjs.read()
match_result = search_regex.search(file_contents)
if match_result is None:
file_contents = file_contents + '\n' + replaceExp
if debug:
print('No match: added new line to end of file contents:', replaceExp)
else:
file_contents = search_regex.sub(replaceExp, file_contents)
if debug:
print('Match found. Modified existing line in file.')
file_userjs.seek(0)
file_userjs.truncate()
file_userjs.write(file_contents)
elif debug:
print("SKIPPED: invalid file:", user_js_path)
그런 다음 다음과 같은 기능을 사용했습니다.
import sys
sys.path = ['/path/to/parent/of/modtest'] + sys.path # if needed
from modtest import ffutils
my_profiles = ffutils.find_profile_dirs()
srchexp = r'^/*?user_pref\("browser\.ctrlTab\.sortByRecentlyUsed.*$'
replexp = 'user_pref("browser.ctrlTab.sortByRecentlyUsed", true);'
ffutils.process_userjs(srchexp, replexp, my_profiles, True)
물론 다른 검색을 사용하여 이를 반복하고 문자열을 바꿀 수도 있습니다.
나는 이것을 개선할 수 있는 방법이 있다고 확신합니다. 나는 다른 답변을 받아들이겠지만, 다른 답변이 없을 경우를 대비해 여기에 내 답변을 넣습니다.
내 코드에는 몇 가지 가정이 있습니다. 한 가지 큰 문제는 모든 Firefox 프로필 경로가 상대적이라고 가정한다는 것입니다. 이것이 유효한 가정이 아닌 경우에는profiles.ini에 대한 추가 처리가 필요합니다.