awesome-bash icon indicating copy to clipboard operation
awesome-bash copied to clipboard

Remove some unmaintained or old non-Bash projects

Open hyperupcall opened this issue 1 month ago • 0 comments

Description

From this comment, we've historically been lax with non-Bash submissions. I used AI to quickly write up a quick script to identify these cases (it identifies GitHub repository links that have a non-Bash/Shell majority of code.

I get these repositories:

Checking 91 GitHub repositories...
NOT BASH: [1/91] https://github.com/alebcay/awesome-shell
NOT BASH: [3/91] https://github.com/bucaran/awesome-fish
NOT BASH: [4/91] https://github.com/sindresorhus/awesome
NOT BASH: [5/91] https://github.com/denysdovhan/bash-handbook
NOT BASH: [6/91] https://github.com/denysdovhan/learnyoubash
NOT BASH: [8/91] https://github.com/anordal/shellharden
NOT BASH: [9/91] https://github.com/sebglazebrook/aliases
NOT BASH: [10/91] https://github.com/rcaloras/bashhub-client
NOT BASH: [11/91] https://github.com/nicksherron/bashhub-server
NOT BASH: [17/91] https://github.com/dvorka/hstr
NOT BASH: [18/91] https://github.com/pindexis/qfc
NOT BASH: [21/91] https://github.com/ajeetdsouza/zoxide
NOT BASH: [30/91] https://github.com/horosgrisa/mysql-colorize.bash
NOT BASH: [36/91] https://github.com/zalando/bigbash
NOT BASH: [55/91] https://github.com/huytd/6a1a6a7b34a0d0abcac00b47e3d01513
NOT BASH: [56/91] https://github.com/janosgyerik/bashoneliners
NOT BASH: [62/91] https://github.com/matejak/argbash
NOT BASH: [70/91] https://github.com/DannyBen/bashly
NOT BASH: [81/91] https://github.com/koalaman/shellcheck
NOT BASH: [82/91] https://github.com/anordal/shellharden
NOT BASH: [83/91] https://github.com/mvdan/sh
NOT BASH: [90/91] https://github.com/emijrp/awesome-awesome
NOT BASH: [91/91] https://github.com/bayandin/awesome-awesomeness

In this PR I've removed some of them that haven't been updated in many many years and aren't super popular.

But there are definitely ones like shellcheck, shellharden, etc. that I really think should remain on this list. Maybe the contribution guidelines can be updated to say that if it is a non-Bash project, it must have at least 1,500 GitHub stars?

check.ts
#!/usr/bin/env -S deno run --allow-net --allow-read

interface GitHubRepo {
	owner: string
	repo: string
}

async function parseMarkdownLinks(filePath: string): Promise<string[]> {
	const content = await Deno.readTextFile(filePath)
	const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g
	const links: string[] = []

	let match
	while ((match = linkRegex.exec(content)) !== null) {
		links.push(match[2])
	}

	return links
}

function parseGitHubUrl(url: string): GitHubRepo | null {
	const match = url.match(/github\.com\/([^\/]+)\/([^\/\?#]+)/)
	if (!match) return null

	return {
		owner: match[1],
		repo: match[2],
	}
}

async function getRepoLanguages(
	owner: string,
	repo: string,
): Promise<Record<string, number> | null> {
	try {
		const token = Deno.env.get('GITHUB_TOKEN')
		const headers: Record<string, string> = {
			'User-Agent': 'awesome-bash-checker',
		}

		if (token) {
			headers['Authorization'] = `Bearer ${token}`
		}

		const response = await fetch(
			`https://api.github.com/repos/${owner}/${repo}/languages`,
			{ headers },
		)

		if (response.status === 403) {
			console.error(`Rate limited. Waiting 10s...`)
			await new Promise((resolve) => setTimeout(resolve, 10_000))
			return getRepoLanguages(owner, repo)
		}

		if (!response.ok) return null

		const languages = await response.json()
		return languages
	} catch (error) {
		console.error(`Error fetching ${owner}/${repo}: ${error.message}`)
		return null
	}
}

function getPrimaryLanguage(languages: Record<string, number>): string | null {
	if (!languages || Object.keys(languages).length === 0) return null

	const sortedLanguages = Object.entries(languages).sort(
		([, a], [, b]) => b - a,
	)

	return sortedLanguages[0][0]
}

function isBashShell(language: string | null): boolean {
	if (!language) return false
	const bashLangs = ['shell', 'bash']
	return bashLangs.includes(language.toLowerCase())
}

async function main() {
	const links = await parseMarkdownLinks('README.md')
	const githubLinks = links
		.map(parseGitHubUrl)
		.filter((repo): repo is GitHubRepo => repo !== null)

	console.error(`Checking ${githubLinks.length} GitHub repositories...`)

	for (let i = 0; i < githubLinks.length; i++) {
		const { owner, repo } = githubLinks[i]

		const languages = await getRepoLanguages(owner, repo)
		const primaryLanguage = getPrimaryLanguage(languages)
		if (!isBashShell(primaryLanguage)) {
			console.error(
				`NOT BASH: [${i + 1}/${githubLinks.length}] ${owner}/${repo}`,
			)
		}

		// Rate limiting: wait 1s between requests to avoid hitting limits
		await new Promise((resolve) => setTimeout(resolve, 1000))
	}
}

if (import.meta.main) {
	main()
}

hyperupcall avatar Nov 21 '25 07:11 hyperupcall